/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.pdx;

import java.lang.reflect.Field;
import java.util.Collections;
import java.util.List;
import java.util.Properties;

import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Declarable;
import org.apache.geode.cache.RegionService;
import org.apache.geode.pdx.internal.AutoSerializableManager;

/**
 * This class uses Java reflection in conjunction with {@link org.apache.geode.pdx.PdxSerializer
 * PdxSerialzer} to perform automatic serialization of domain objects. The implication is that the
 * domain classes do not need to implement the <code>PdxSerializable</code> interface.
 * <p>
 * This implementation will serialize all relevant fields
 * <p>
 * For example:
 *
 * <pre>
 * Cache c = new CacheFactory().set(&quot;cache-xml-file&quot;, cacheXmlFileName)
 *     .setPdxSerializer(new ReflectionBasedAutoSerializer("com.foo.DomainObject")).create();
 * </pre>
 * <p>
 * In this example <code>DomainObject</code> would not need to implement
 * <code>PdxSerializable</code> to be serialized.
 * <p>
 * The equivalent <code>cache.xml</code> entries might be as follows:
 *
 * <pre>
 * &lt;pdx&gt;
 *   &lt;pdx-serializer&gt;
 *     &lt;class-name&gt;
 *       org.apache.geode.pdx.ReflectionBasedAutoSerializer
 *     &lt;/class-name&gt;
 *     &lt;parameter name="classes"&gt;
 *       &lt;string&gt; com.company.domain.DomainObject &lt;/string&gt;
 *     &lt;/parameter&gt;
 *   &lt;/pdx-serializer&gt;
 * &lt;/pdx&gt;
 * </pre>
 *
 * See {@link ReflectionBasedAutoSerializer#reconfigure(String...) reconfigure} for additional
 * details on the format of the parameter string.
 *
 * @since GemFire 6.6
 */
public class ReflectionBasedAutoSerializer implements PdxSerializer, Declarable {

  private final AutoSerializableManager manager;

  /**
   * Default constructor primarily used during declarative configuration via the cache.xml file.
   * Instances created with this constructor will not match any classes so use
   * {@link #ReflectionBasedAutoSerializer(String...)} instead.
   */
  public ReflectionBasedAutoSerializer() {
    this(new String[0]);
  }

  /**
   * Constructor which takes a list of class name patterns which are to be auto-serialized.
   * Portability of serialization will not be checked.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param classes the patterns which are matched against domain class names to determine whether
   *        they should be serialized
   * @deprecated as of 6.6.2 use ReflectionBasedAutoSerializer(String...) instead.
   */
  public ReflectionBasedAutoSerializer(List<String> classes) {
    this(listToArray(classes));
  }

  private static String[] listToArray(List<String> l) {
    if (l == null) {
      l = Collections.emptyList();
    }
    return l.toArray(new String[l.size()]);
  }

  /**
   * Constructor which takes a list of class name patterns which are to be auto-serialized.
   * Portability of serialization will not be checked.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param patterns the patterns which are matched against domain class names to determine whether
   *        they should be serialized
   * @since GemFire 6.6.2
   */
  public ReflectionBasedAutoSerializer(String... patterns) {
    this(false, patterns);
  }

  /**
   * Constructor which takes a list of class name patterns which are to be auto-serialized.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param checkPortability if <code>true</code> then an serialization done by this serializer will
   *        throw an exception if the object it not portable to non-java languages.
   * @param patterns the patterns which are matched against domain class names to determine whether
   *        they should be serialized
   * @since GemFire 6.6.2
   */
  public ReflectionBasedAutoSerializer(boolean checkPortability, String... patterns) {
    // We allow this class to escape its constructor so that our delegate can
    // call back to us when needed. Callbacks will not happen until this instance
    // is fully constructed and registered with the Cache.
    this.manager = AutoSerializableManager.create(this, checkPortability, patterns);
  }

  /**
   * Method to configure classes to consider for serialization, to set any identity fields and to
   * define any fields to exclude from serialization.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param patterns the list of definitions to apply
   * @deprecated as of 6.6.2 use {@link #reconfigure(String...)} instead.
   */
  public void setSerializableClasses(List<String> patterns) {
    reconfigure(listToArray(patterns));
  }

  /**
   * Method to reconfigure this serializer. Any previous configuration is cleared. The serializer
   * will not check for portable serialization.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param patterns the definitions to apply
   * @since GemFire 6.6.2
   */
  public void reconfigure(String... patterns) {
    reconfigure(false, patterns);
  }

  /**
   * Method to reconfigure this serializer. Any previous configuration is cleared.
   * <p>
   * Each string in the list represents a definition in the following form:
   *
   * <pre>
   *   &lt;class pattern&gt;#identity=&lt;identity field pattern&gt;#exclude=&lt;exclude field pattern&gt;
   * </pre>
   *
   * The hash (#) characters are separators and are not part of the parameter name. An example would
   * be:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*#exclude=creationDate
   * </pre>
   *
   * This would select all classes with a class name beginning with
   * <code>com.company.DomainObject</code> and would select as PDX identity fields any fields
   * beginning with <code>id</code> and would not serialize the field called
   * <code>creationDate</code>.
   * <p>
   * There is no association between the the <i>identity</i> and <i>exclude</i> options, so the
   * above example could also be expressed as:
   *
   * <pre>
   *   com.company.DomainObject.*#identity=id.*
   *   com.company.DomainObject.*#exclude=creationDate
   * </pre>
   *
   * Note that <u>all</u> defined patterns are used when determining whether a field should be
   * considered as an identity field or should be excluded. Thus the order of the patterns is not
   * relevant.
   *
   * @param patterns the definitions to apply
   * @param checkPortability if <code>true</code> then an serialization done by this serializer will
   *        throw an exception if the object it not portable to non-java languages.
   * @since GemFire 6.6.2
   */
  public void reconfigure(boolean checkPortability, String... patterns) {
    this.manager.reconfigure(checkPortability, patterns);
  }

  /**
   * Method implemented from <code>PdxSerializer</code> which performs object serialization.
   *
   * @param obj the object to serialize
   * @param writer the <code>PdxWriter</code> to use when serializing this object
   * @return <code>true</code> if the object was serialized, <code>false</code> otherwise
   */
  @Override
  public boolean toData(Object obj, PdxWriter writer) {
    return manager.writeData(writer, obj);
  }

  /**
   * Method implemented from <code>PdxSerializer</code> which performs object de-serialization.
   *
   * @param clazz the class of the object to re-create
   * @param reader the <code>PdxReader</code> to use when creating this object
   * @return the deserialized object if this serializer handles the given class, null otherwise.
   */
  @Override
  public Object fromData(Class<?> clazz, PdxReader reader) {
    return manager.readData(reader, clazz);
  }

  /**
   * Used for declarative class initialization from cache.xml. The following property may be
   * specified:
   * <ul>
   * <li><b>classes</b> - a comma-delimited list of strings which represent the patterns used to
   * select classes for serialization, patterns to select identity fields and patterns to exclude
   * fields. See {@link ReflectionBasedAutoSerializer#reconfigure(String...) reconfigure} for
   * specifics.</li>
   * <li><b>check-portability</b> - if true then an exception will be thrown if an attempt to
   * serialize data that is not portable to .NET is made.
   *
   * @param props properties used to configure the auto serializer
   * @deprecated as of Geode 1.5 use initialize instead
   */
  @Override
  public void init(Properties props) {
    this.manager.init(props);
  }

  /**
   * Used for declarative class initialization from cache.xml. The following property may be
   * specified:
   * <ul>
   * <li><b>classes</b> - a comma-delimited list of strings which represent the patterns used to
   * select classes for serialization, patterns to select identity fields and patterns to exclude
   * fields. See {@link ReflectionBasedAutoSerializer#reconfigure(String...) reconfigure} for
   * specifics.</li>
   * <li><b>check-portability</b> - if true then an exception will be thrown if an attempt to
   * serialize data that is not portable to .NET is made.
   *
   * @param cache the cache that owns this serializer
   * @param props properties used to configure the auto serializer
   * @since Geode 1.5
   */
  @Override
  public void initialize(Cache cache, Properties props) {
    this.manager.setRegionService(cache);
    this.manager.init(props);
  }

  /**
   * Return a <code>Properties</code> object with a representation of the current config. Depending
   * on how this <code>ReflectionBasedAutoSerializer</code> was configured, the returned property
   * value will have the correct semantics but may differ from the the original configuration
   * string.
   *
   * @return a <code>Properties</code> object
   */
  public Properties getConfig() {
    return this.manager.getConfig();
  }

  /**
   * Controls what classes will be auto serialized by this serializer. Override this method to
   * customize what classes will be auto serialized.
   * <p>
   * The default implementation:
   * <ul>
   * <li>only serializes classes whose name matches one of the patterns
   * <li>excludes classes whose package begins with "org.apache.", "java.", or "javax." unless the
   * system property "gemfire.auto.serialization.no.hardcoded.excludes" is set to "true".
   * <li>excludes classes that do not have a public no-arg constructor
   * <li>excludes enum classes
   * <li>excludes classes that require standard java serialization. A class requires standard java
   * serialization if it extends Externalizable or if it extends Serializable and has either a
   * private writeObject method or a writeReplace method as defined by the java serialization
   * specification.
   * </ul>
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param clazz the class that is being considered for auto serialization.
   * @return true if instances of the class should be auto serialized; false if not.
   * @since GemFire 6.6.2
   */
  public boolean isClassAutoSerialized(Class<?> clazz) {
    return this.manager.defaultIsClassAutoSerialized(clazz);
  }

  /**
   * Controls what fields of a class will be auto serialized by this serializer. Override this
   * method to customize what fields of a class will be auto serialized.
   * <p>
   * The default implementation:
   * <ul>
   * <li>excludes transient fields
   * <li>excludes static fields
   * <li>excludes any fields that match an "#exclude=" pattern.
   * </ul>
   * All other fields are included.
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param f the field being considered for serialization
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @return true if the field should be serialized as a pdx field; false if it should be ignored.
   * @since GemFire 6.6.2
   */
  public boolean isFieldIncluded(Field f, Class<?> clazz) {
    return this.manager.defaultIsFieldIncluded(f, clazz);
  }

  /**
   * Controls the field name that will be used in pdx for a field being auto serialized. Override
   * this method to customize the field names that will be generated by auto serialization. It
   * allows you to convert a local, language dependent name, to a more portable name. The returned
   * name is the one that will show up in a {@link PdxInstance} and that one that will need to be
   * used to access the field when doing a query.
   * <p>
   * The default implementation returns the name obtained from <code>f</code>.
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param f the field whose name is returned.
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @return the name of the field
   * @since GemFire 6.6.2
   */
  public String getFieldName(Field f, Class<?> clazz) {
    return f.getName();
  }

  /**
   * Controls what fields of a class that is auto serialized will be marked as pdx identity fields.
   * Override this method to customize what fields of an auto serialized class will be identity
   * fields. Identity fields are used when a {@link PdxInstance} computes its hash code and checks
   * to see if it is equal to another object.
   * <p>
   * The default implementation only marks fields that match an "#identity=" pattern as identity
   * fields.
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param f the field to test to see if it is an identity field.
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @return true if the field should be marked as an identity field; false if not.
   * @since GemFire 6.6.2
   */
  public boolean isIdentityField(Field f, Class<?> clazz) {
    return this.manager.defaultIsIdentityField(f, clazz);
  }

  /**
   * Controls what pdx field type will be used when auto serializing. Override this method to
   * customize what pdx field type will be used for a given domain class field.
   * <p>
   * The default implementation uses {@link FieldType#get(Class)} by passing it
   * {@link Field#getType()}.
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param f the field whose pdx field type needs to be determined
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @return the pdx field type of the given domain class field.
   * @since GemFire 6.6.2
   */
  public FieldType getFieldType(Field f, Class<?> clazz) {
    return this.manager.defaultGetFieldType(f, clazz);
  }

  /**
   * Controls if a pdx field's value can be transformed during serialization. Override this method
   * to customize what fields can have their values transformed. If you return true then you need to
   * also override {@link #writeTransform} and {@link #readTransform}.
   * <p>
   * The default implementation returns false.
   * <p>
   * This method is only called the first time it sees a new class. The result will be remembered
   * and used the next time the same class is seen.
   *
   * @param f the field in question
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @return true if the {@link #writeTransform} and {@link #readTransform} need to be called when
   *         serializing and deserializing this field's value.
   * @since GemFire 6.6.2
   */
  public boolean transformFieldValue(Field f, Class<?> clazz) {
    return false;
  }

  /**
   * Controls what field value is written during auto serialization. Override this method to
   * customize the data that will be written during auto serialization. This method will only be
   * called if {@link #transformFieldValue} returned true.
   *
   * @param f the field in question
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @param originalValue the value of the field that was read from the domain object.
   * @return the actual value to write for this field. Return <code>originalValue</code> if you
   *         decide not to transform the value.
   * @since GemFire 6.6.2
   */
  public Object writeTransform(Field f, Class<?> clazz, Object originalValue) {
    return originalValue;
  }

  /**
   * Controls what field value is read during auto deserialization. Override this method to
   * customize the data that will be read during auto deserialization. This method will only be
   * called if {@link #transformFieldValue} returned true.
   *
   * @param f the field in question
   * @param clazz the original class being serialized that owns this field. Note that this field may
   *        have been inherited from a super class by this class. If you want to find the class that
   *        declared this field use {@link Field#getDeclaringClass()}.
   * @param serializedValue the value of the field that was serialized for this field.
   * @return the actual value to write for this field. Return <code>serializedValue</code> if you
   *         decide not to transform the value.
   * @since GemFire 6.6.2
   */
  public Object readTransform(Field f, Class<?> clazz, Object serializedValue) {
    return serializedValue;
  }

  /**
   * Returns the cache that this serializer is installed on. Returns null if it is not installed.
   *
   * @since GemFire 6.6.2
   */
  public RegionService getRegionService() {
    return this.manager.getRegionService();
  }

  /**
   * For internal use only.
   *
   * @since GemFire 8.2
   */
  public Object getManager() {
    // The result is not AutoSerializableManager because
    // that class is not part of our public APIs.
    return this.manager;
  }
}
