code: /*
   * Copyright 2012-2018 Chronicle Map Contributors
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  package net.openhft.chronicle.hash.serialization.impl;
  
  import net.openhft.chronicle.core.util.ObjectUtils;
  import net.openhft.chronicle.hash.Data;
  import net.openhft.chronicle.hash.serialization.DataAccess;
  import net.openhft.chronicle.hash.serialization.SizedReader;
  import net.openhft.chronicle.map.ChronicleMapBuilder;
  import net.openhft.chronicle.wire.Marshallable;
  import net.openhft.chronicle.wire.WireIn;
  import net.openhft.chronicle.wire.WireOut;
  import org.jetbrains.annotations.NotNull;
  
  import java.lang.reflect.Type;
  
  /**
   * Holds new instance creation logic, common for many {@link DataAccess} and {@link SizedReader}
   * implementations
   *
   * @param <T> the type of objects deserialized
   */
  public abstract class InstanceCreatingMarshaller<T> implements Marshallable {
  
      private Type tClass;
  
      /**
       * Constructor for use in subclasses.
       *
       * @param tClass the class of objects deserialized
       */
      protected InstanceCreatingMarshaller(Class<T> tClass) {
          this.tClass = tClass;
      }
  
      protected InstanceCreatingMarshaller(Type tClass) {
          this.tClass = tClass;
      }
  
      /**
       * Returns the class of objects deserialized.
       */
      protected Class<T> tClass() {
          return (Class<T>) tClass;
      }
  
      protected Type tType() {
          return tClass;
      }
  
      /**
       * Creates a new {@code T} instance by calling {@link Class#newInstance()}. If you need
       * different logic, i. e. calling a constructor with parameter, override this method in a
       * subclass of the specific {@link DataAccess} or {@link SizedReader} and configure in {@link
       * ChronicleMapBuilder}.
       *
       * @return a new instance to return from {@link Data#getUsing(Object)} or {@link
       * SizedReader#read(net.openhft.chronicle.bytes.Bytes, long, Object)} method
       */
      protected T createInstance() {
          try {
              return ObjectUtils.newInstance(tClass());
          } catch (Exception e) {
              throw new IllegalStateException("Some of default marshallers, chosen for the type\n" +
                      tClass + " by default, delegate to \n" +
                      this.getClass().getName() + " which assumes the type has a public no-arg\n" +
                      "constructor. If this is not true, you should either extend the marshaller,\n" +
                      "overriding createInstance() and copy() (if defined), and the extending\n" +
                      "class shouldn't be inner, because such classes couldn't be Serializable\n" +
                      "that is a requirement for marshaller classes, or write and configure your\n" +
                      "own marshaller for " + tClass + " type from scratch, and configure for the\n" +
                      "Chronicle Map via keyMarshaller[s]() or valueMarshaller[s]() methods", e);
          }
      }
  
      @Override
      public void readMarshallable(@NotNull WireIn wireIn) {
          //noinspection unchecked
          tClass = wireIn.read(() -> "tClass").lenientTypeLiteral();
      }
  
      @Override
      public void writeMarshallable(@NotNull WireOut wireOut) {
          wireOut.write(() -> "tClass").typeLiteral(tClass);
      }
  }
  