/*
 * 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.internal;

import java.io.Externalizable;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.regex.Pattern;

import org.apache.logging.log4j.Logger;

import org.apache.geode.CancelException;
import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.RegionService;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.CopyOnWriteHashSet;
import org.apache.geode.internal.PdxSerializerObject;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.internal.util.concurrent.CopyOnWriteWeakHashMap;
import org.apache.geode.pdx.FieldType;
import org.apache.geode.pdx.NonPortableClassException;
import org.apache.geode.pdx.PdxReader;
import org.apache.geode.pdx.PdxSerializationException;
import org.apache.geode.pdx.PdxWriter;
import org.apache.geode.pdx.ReflectionBasedAutoSerializer;
import org.apache.geode.pdx.internal.unsafe.UnsafeWrapper;

/**
 * The core of auto serialization which is used in both aspect and reflection-based
 * auto-serialization. This simple manager class is a singleton which tracks the relevant fields for
 * each class which is to be auto-serialized. This class used to be a singleton. But now every
 * instance of ReflectionBasedAutoSerializer will have its own instance of this class. We allow
 * instances of this class to be found so that tests can access internal apis that are not exposed
 * on the public ReflectionBasedAutoSerializer.
 *
 * @since GemFire 6.6
 */

public class AutoSerializableManager {
  private static final Logger logger = LogService.getLogger();

  private static final String INIT_CLASSES_PARAM = "classes";
  private static final String INIT_CHECK_PORTABILITY_PARAM = "check-portability";
  private static final String OPT_IDENTITY = "identity";
  private static final String OPT_EXCLUDE = "exclude";

  /*
   * Map of class and list of fields, we're interested in, for that class.
   */
  private final Map<Class<?>, AutoClassInfo> classMap =
      new CopyOnWriteWeakHashMap<Class<?>, AutoClassInfo>();

  /*
   * Mapping between class patterns and identity field patterns.
   */
  private final List<String[]> identityPatterns = new CopyOnWriteArrayList<String[]>();

  /*
   * Mapping between class patterns and patterns of fields to exclude
   */
  private final List<String[]> excludePatterns = new CopyOnWriteArrayList<String[]>();

  /*
   * This is an internal parameter which, when set either as a system property or via cache.xml will
   * not evaluate any hardcoded excludes. This helps with testing as well as possibly debugging
   * future customer issues.
   */
  public static final String NO_HARDCODED_EXCLUDES_PARAM =
      DistributionConfig.GEMFIRE_PREFIX + "auto.serialization.no.hardcoded.excludes";

  private boolean noHardcodedExcludes = Boolean.getBoolean(NO_HARDCODED_EXCLUDES_PARAM);


  /*
   * Holds a set of regex patterns which match the list of classes we're interested in.
   */
  private final Set<Pattern> classPatterns = new LinkedHashSet<Pattern>();

  /*
   * Hardcoded set of patterns which we always exclude.
   */
  private Set<Pattern> hardcodedExclusions = new HashSet<Pattern>() {
    {
      add(Pattern.compile("org\\.apache\\.geode\\..*"));
      add(Pattern.compile("com\\.gemstone\\..*"));
      add(Pattern.compile("java\\..*"));
      add(Pattern.compile("javax\\..*"));
    }
  };

  /*
   * Cache of class names which have been determined to be excluded from serialization. Built up
   * within isRelevant().
   */
  private final Set<String> cachedExcludedClasses = new CopyOnWriteHashSet<String>();

  /*
   * Cache of class names which have been determined to be included for serialization. Built up
   * within isRelevant().
   */
  private final Set<String> cachedIncludedClasses = new CopyOnWriteHashSet<String>();

  /*
   * Used to hold the class names which have triggered a warning because they have been determined
   * that they should be auto serialized based on a pattern much but were not because that either do
   * not have a public no-arg constructor or have explicit java serialization code.
   */
  private final Set<String> loggedNoAutoSerializeMsg = new CopyOnWriteHashSet<String>();


  private final ReflectionBasedAutoSerializer owner;

  public ReflectionBasedAutoSerializer getOwner() {
    return this.owner;
  }

  public static AutoSerializableManager create(ReflectionBasedAutoSerializer owner,
      boolean checkPortability, String... patterns) {
    AutoSerializableManager result = new AutoSerializableManager(owner);
    result.reconfigure(checkPortability, patterns);
    return result;
  }

  private AutoSerializableManager(ReflectionBasedAutoSerializer owner) {
    this.owner = owner;
  }

  public Map<Class<?>, AutoClassInfo> getClassMap() {
    return classMap;
  }

  private boolean checkPortability;

  public void setCheckPortability(boolean b) {
    this.checkPortability = b;
  }

  public boolean getCheckPortability() {
    return this.checkPortability;
  }

  public void resetCachedTypes() {
    classMap.clear();
  }

  public void resetCaches() {
    identityPatterns.clear();
    excludePatterns.clear();
    resetCachedTypes();
  }

  public void resetAll() {
    resetCaches();
    this.checkPortability = false;
    classPatterns.clear();
    cachedIncludedClasses.clear();
    cachedExcludedClasses.clear();
    loggedNoAutoSerializeMsg.clear();
    this.noHardcodedExcludes = Boolean.getBoolean(NO_HARDCODED_EXCLUDES_PARAM);
  }

  /*
   * Helper method to determine whether the class of a given object is a class which we are
   * interested in (de)serializing.
   *
   *
   * @return true if the object should be considered for serialization or false otherwise
   */
  private boolean isRelevant(Class<?> clazz) {
    String className = clazz.getName();

    // Do some short-circuiting if possible
    if (cachedIncludedClasses.contains(className)) {
      return true;
    } else if (cachedExcludedClasses.contains(className)) {
      return false;
    }

    boolean result = getOwner().isClassAutoSerialized(clazz);
    if (result) {
      cachedIncludedClasses.add(className);
    } else {
      cachedExcludedClasses.add(className);
    }
    return result;
  }

  /**
   * Determines whether objects of the named class are excluded from auto-serialization. The classes
   * that are excluded are Geode-internal classes and Java classes.
   *
   * @param className Class name including packages.
   * @return <code>true</code> if the named class is excluded.
   */
  public boolean isExcluded(String className) {
    if (!noHardcodedExcludes) {
      for (Pattern p : hardcodedExclusions) {
        if (p.matcher(className).matches()) {
          return true;
        }
      }
    }
    return false;
  }

  public boolean defaultIsClassAutoSerialized(Class<?> clazz) {
    if (clazz.isEnum()) {
      return false;
    }
    String className = clazz.getName();
    if (isExcluded(className)) {
      if (!PdxSerializerObject.class.isAssignableFrom(clazz)) {
        return false;
      }
    }

    for (Pattern p : classPatterns) {
      if (p.matcher(className).matches()) {
        if (hasValidConstructor(clazz, p) && !needsStandardSerialization(clazz, p)) {
          return true;
        } else {
          return false;
        }
      }
    }
    return false;
  }

  /*
   * Helper method to determine whether a class has a default constructor. That's needed so that it
   * can be re-instantiated by PDX on de-serialization.
   *
   */
  private boolean hasValidConstructor(Class<?> clazz, Pattern matchedPattern) {
    if (unsafe != null && !USE_CONSTRUCTOR) {
      // unsafe allows us to create instances without a constructor
      return true;
    }
    try {
      clazz.getConstructor();
      return true;
    } catch (NoSuchMethodException nex) {
      String className = clazz.getName();
      if (!loggedNoAutoSerializeMsg.contains(className)) {
        loggedNoAutoSerializeMsg.add(className);
        logger.warn(
            "Class {} matched with '{}' cannot be auto-serialized due to missing public no-arg constructor. Will attempt using Java serialization.",
            className, matchedPattern.pattern());
      }
      return false;
    }
  }

  private boolean needsStandardSerialization(Class<?> clazz, Pattern matchedPattern) {
    if (Serializable.class.isAssignableFrom(clazz)) {
      if (Externalizable.class.isAssignableFrom(clazz)) {
        String className = clazz.getName();
        if (!loggedNoAutoSerializeMsg.contains(className)) {
          loggedNoAutoSerializeMsg.add(className);
          logger.warn(
              "Class {} matched with '{}' cannot be auto-serialized because it is Externalizable. Java serialization will be used instead of auto-serialization.",
              className, matchedPattern.pattern());
        }
        return true;
      } else {
        if (getPrivateMethod(clazz, "writeObject", new Class[] {ObjectOutputStream.class},
            Void.TYPE)) {
          String className = clazz.getName();
          if (!loggedNoAutoSerializeMsg.contains(className)) {
            loggedNoAutoSerializeMsg.add(className);
            logger.warn(
                "Class {} matched with '{}' cannot be auto-serialized because it has a writeObject(ObjectOutputStream) method. Java serialization will be used instead of auto-serialization.",
                className, matchedPattern.pattern());
          }
          return true;
        } else if (getInheritableMethod(clazz, "writeReplace", null, Object.class)) {
          String className = clazz.getName();
          if (!loggedNoAutoSerializeMsg.contains(className)) {
            loggedNoAutoSerializeMsg.add(className);
            logger.warn(
                "Class {} matched with '{}' cannot be auto-serialized because it has a writeReplace() method. Java serialization will be used instead of auto-serialization.",
                className, matchedPattern.pattern());
          }
          return true;
        }
      }
    }
    return false;
  }

  /**
   * Returns true if a non-private static method with given signature defined by given class, or
   * false if none found.
   */
  private static boolean getPrivateMethod(Class cl, String name, Class[] argTypes,
      Class returnType) {
    try {
      Method meth = cl.getDeclaredMethod(name, argTypes);
      int mods = meth.getModifiers();
      return ((meth.getReturnType() == returnType) && ((mods & Modifier.STATIC) == 0)
          && ((mods & Modifier.PRIVATE) != 0));
    } catch (NoSuchMethodException ex) {
      return false;
    }
  }

  /**
   * Returns true if a non-static, non-abstract method with given signature provided it is defined
   * by or accessible (via inheritance) by the given class, or false if no match found.
   */
  private static boolean getInheritableMethod(Class cl, String name, Class[] argTypes,
      Class returnType) {
    Method meth = null;
    Class defCl = cl;
    while (defCl != null) {
      try {
        meth = defCl.getDeclaredMethod(name, argTypes);
        break;
      } catch (NoSuchMethodException ex) {
        defCl = defCl.getSuperclass();
      }
    }

    if ((meth == null) || (meth.getReturnType() != returnType)) {
      return false;
    }
    int mods = meth.getModifiers();
    if ((mods & (Modifier.STATIC | Modifier.ABSTRACT)) != 0) {
      return false;
    } else if ((mods & (Modifier.PUBLIC | Modifier.PROTECTED)) != 0) {
      return true;
    } else if ((mods & Modifier.PRIVATE) != 0) {
      return (cl == defCl);
    } else {
      return packageEquals(cl, defCl);
    }
  }

  /**
   * Returns true if classes are defined in the same runtime package, false otherwise.
   */
  private static boolean packageEquals(Class cl1, Class cl2) {
    return (cl1.getClassLoader() == cl2.getClassLoader()
        && getPackageName(cl1).equals(getPackageName(cl2)));
  }

  /**
   * Returns package name of given class.
   */
  private static String getPackageName(Class cl) {
    String s = cl.getName();
    int i = s.lastIndexOf('[');
    if (i >= 0) {
      s = s.substring(i + 2);
    }
    i = s.lastIndexOf('.');
    return (i >= 0) ? s.substring(0, i) : "";
  }

  /**
   * Given a class, figure out which fields we're interested in serializing. The class' entire
   * hierarchy will be traversed and used. Transients and statics will be ignored.
   *
   * @param clazz the <code>Class</code> we're interested in
   * @return a list of fields to be used when this class is (de)serialized
   */
  public List<PdxFieldWrapper> getFields(Class<?> clazz) {
    return getClassInfo(clazz).getFields();

  }

  public AutoClassInfo getExistingClassInfo(Class<?> clazz) {
    return classMap.get(clazz);
  }

  public AutoClassInfo getClassInfo(Class<?> clazz) {
    Class<?> tmpClass = clazz;
    AutoClassInfo classInfo = getExistingClassInfo(tmpClass);
    if (classInfo == null) {
      synchronized (classMap) {
        classInfo = classMap.get(tmpClass);
        if (classInfo != null)
          return classInfo;

        List<PdxFieldWrapper> fieldList = new ArrayList<PdxFieldWrapper>();
        List<PdxFieldWrapper> variableLenFields = new ArrayList<PdxFieldWrapper>();

        while (tmpClass != Object.class) {
          Field[] fields = tmpClass.getDeclaredFields();
          for (Field f : fields) {
            if (getOwner().isFieldIncluded(f, clazz)) {
              // Should this be reset at some point?
              f.setAccessible(true);
              FieldType ft = getOwner().getFieldType(f, clazz);
              PdxFieldWrapper fw = PdxFieldWrapper.create(this, f, ft,
                  getOwner().getFieldName(f, clazz), getOwner().transformFieldValue(f, clazz),
                  getOwner().isIdentityField(f, clazz));
              if (ft.isFixedWidth()) {
                fieldList.add(fw);
              } else {
                variableLenFields.add(fw);
              }
            }
          }
          tmpClass = tmpClass.getSuperclass();
        }

        fieldList.addAll(variableLenFields);
        classInfo = new AutoClassInfo(clazz, fieldList);
        logger.info("Auto serializer generating type for {} for fields: {}", clazz,
            classInfo.toFormattedString());
        classMap.put(clazz, classInfo);
      } // end sync
    }
    return classInfo;
  }

  public boolean defaultIsIdentityField(Field f, Class<?> clazz) {
    return fieldMatches(f, clazz.getName(), identityPatterns);
  }

  public boolean defaultIsFieldIncluded(Field f, Class<?> clazz) {
    return !Modifier.isTransient(f.getModifiers()) && !Modifier.isStatic(f.getModifiers())
        && !fieldMatches(f, clazz.getName(), excludePatterns);
  }

  public FieldType defaultGetFieldType(Field f, Class<?> clazz) {
    return FieldType.get(f.getType());
  }

  private static class FieldWrapper {
    private final Field field;

    public FieldWrapper(Field f) {
      this.field = f;
    }

    public Field getField() {
      return this.field;
    }

    public int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getInt(o);
    }

    public void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
      this.field.setInt(o, v);
    }

    public boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getBoolean(o);
    }

    public void setBoolean(Object o, boolean v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setBoolean(o, v);
    }

    public byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getByte(o);
    }

    public void setByte(Object o, byte v) throws IllegalArgumentException, IllegalAccessException {
      this.field.setByte(o, v);
    }

    public short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getShort(o);
    }

    public void setShort(Object o, short v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setShort(o, v);
    }

    public char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getChar(o);
    }

    public void setChar(Object o, char v) throws IllegalArgumentException, IllegalAccessException {
      this.field.setChar(o, v);
    }

    public long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getLong(o);
    }

    public void setLong(Object o, long v) throws IllegalArgumentException, IllegalAccessException {
      this.field.setLong(o, v);
    }

    public float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getFloat(o);
    }

    public void setFloat(Object o, float v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setFloat(o, v);
    }

    public double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getDouble(o);
    }

    public void setDouble(Object o, double v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setDouble(o, v);
    }

    public Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.get(o);
    }

    public void setObject(Object o, Object v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.set(o, v);
    }

    @Override
    public String toString() {
      return field.toString();
    }
  }

  private static class UnsafeFieldWrapper extends FieldWrapper {
    private final long offset;

    public UnsafeFieldWrapper(Field f) {
      super(f);
      this.offset = unsafe.objectFieldOffset(f);
    }

    @Override
    public int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getInt(o, this.offset);
    }

    @Override
    public void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
      unsafe.putInt(o, this.offset, v);
    }

    @Override
    public boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getBoolean(o, this.offset);
    }

    @Override
    public void setBoolean(Object o, boolean v)
        throws IllegalArgumentException, IllegalAccessException {
      unsafe.putBoolean(o, this.offset, v);
    }

    @Override
    public byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getByte(o, this.offset);
    }

    @Override
    public void setByte(Object o, byte v) throws IllegalArgumentException, IllegalAccessException {
      unsafe.putByte(o, this.offset, v);
    }

    @Override
    public short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getShort(o, this.offset);
    }

    @Override
    public void setShort(Object o, short v)
        throws IllegalArgumentException, IllegalAccessException {
      unsafe.putShort(o, this.offset, v);
    }

    @Override
    public char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getChar(o, this.offset);
    }

    @Override
    public void setChar(Object o, char v) throws IllegalArgumentException, IllegalAccessException {
      unsafe.putChar(o, this.offset, v);
    }

    @Override
    public long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getLong(o, this.offset);
    }

    @Override
    public void setLong(Object o, long v) throws IllegalArgumentException, IllegalAccessException {
      unsafe.putLong(o, this.offset, v);
    }

    @Override
    public float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getFloat(o, this.offset);
    }

    @Override
    public void setFloat(Object o, float v)
        throws IllegalArgumentException, IllegalAccessException {
      unsafe.putFloat(o, this.offset, v);
    }

    @Override
    public double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getDouble(o, this.offset);
    }

    @Override
    public void setDouble(Object o, double v)
        throws IllegalArgumentException, IllegalAccessException {
      unsafe.putDouble(o, this.offset, v);
    }

    @Override
    public Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
      return unsafe.getObject(o, this.offset);
    }

    @Override
    public void setObject(Object o, Object v)
        throws IllegalArgumentException, IllegalAccessException {
      unsafe.putObject(o, this.offset, v);
    }
  }

  // unsafe will be null if the Unsafe class is not available or SAFE was requested.
  // We attempt to use Unsafe by default for best performance.
  @Immutable
  private static final UnsafeWrapper unsafe;
  static {
    UnsafeWrapper tmp = null;
    // only use Unsafe if SAFE was not explicitly requested
    if (!Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.SAFE")) {
      try {
        tmp = new UnsafeWrapper();
        // only throw an exception if UNSAFE was explicitly requested
      } catch (RuntimeException ex) {
        if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.UNSAFE")) {
          throw ex;
        }
      } catch (Error ex) {
        if (Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "AutoSerializer.UNSAFE")) {
          throw ex;
        }
      }
    }
    unsafe = tmp;
  }

  public abstract static class PdxFieldWrapper {
    private final FieldWrapper field;
    private final String fieldName;
    private final boolean transformValue;
    private final AutoSerializableManager owner;
    private final boolean isIdentityField;

    protected PdxFieldWrapper(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      FieldWrapper tmp;
      if (unsafe != null) {
        tmp = new UnsafeFieldWrapper(f);
      } else {
        tmp = new FieldWrapper(f);
      }
      this.field = tmp;
      this.fieldName = name;
      this.transformValue = transformValue;
      this.owner = owner;
      this.isIdentityField = isIdentityField;
    }

    public static PdxFieldWrapper create(AutoSerializableManager owner, Field f, FieldType ft,
        String name, boolean transformValue, boolean isIdentityField) {
      switch (ft) {
        case INT:
          return new IntField(owner, f, name, transformValue, isIdentityField);
        case BYTE:
          return new ByteField(owner, f, name, transformValue, isIdentityField);
        case LONG:
          return new LongField(owner, f, name, transformValue, isIdentityField);
        case BOOLEAN:
          return new BooleanField(owner, f, name, transformValue, isIdentityField);
        case CHAR:
          return new CharField(owner, f, name, transformValue, isIdentityField);
        case SHORT:
          return new ShortField(owner, f, name, transformValue, isIdentityField);
        case DOUBLE:
          return new DoubleField(owner, f, name, transformValue, isIdentityField);
        case FLOAT:
          return new FloatField(owner, f, name, transformValue, isIdentityField);
        case STRING:
          return new StringField(owner, f, name, transformValue, isIdentityField);
        case DATE:
          return new DateField(owner, f, name, transformValue, isIdentityField);
        case BYTE_ARRAY:
          return new ByteArrayField(owner, f, name, transformValue, isIdentityField);
        case STRING_ARRAY:
          return new StringArrayField(owner, f, name, transformValue, isIdentityField);
        case ARRAY_OF_BYTE_ARRAYS:
          return new ByteArrayArrayField(owner, f, name, transformValue, isIdentityField);
        case BOOLEAN_ARRAY:
          return new BooleanArrayField(owner, f, name, transformValue, isIdentityField);
        case CHAR_ARRAY:
          return new CharArrayField(owner, f, name, transformValue, isIdentityField);
        case SHORT_ARRAY:
          return new ShortArrayField(owner, f, name, transformValue, isIdentityField);
        case INT_ARRAY:
          return new IntArrayField(owner, f, name, transformValue, isIdentityField);
        case LONG_ARRAY:
          return new LongArrayField(owner, f, name, transformValue, isIdentityField);
        case FLOAT_ARRAY:
          return new FloatArrayField(owner, f, name, transformValue, isIdentityField);
        case DOUBLE_ARRAY:
          return new DoubleArrayField(owner, f, name, transformValue, isIdentityField);
        case OBJECT_ARRAY:
          return new ObjectArrayField(owner, f, name, transformValue, isIdentityField);
        case OBJECT:
          return new ObjectField(owner, f, name, transformValue, isIdentityField);
        default:
          throw new IllegalStateException("unhandled field type " + ft);
      }
    }

    public boolean getCheckPortability() {
      return this.owner.getCheckPortability();
    }

    public Field getField() {
      return this.field.getField();
    }

    public String getName() {
      return this.fieldName;
    }

    public boolean transform() {
      return this.transformValue;
    }

    public abstract void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite);

    public abstract void serializeValue(PdxWriterImpl writer, Object newValue,
        boolean optimizeWrite);

    public abstract void deserialize(InternalPdxReader reader, Object obj);

    public abstract void orderedDeserialize(InternalPdxReader reader, Object obj);

    protected Object readTransformIf(Object o, Object serializedValue)
        throws IllegalArgumentException, IllegalAccessException {
      if (!transform())
        return serializedValue;
      return readTransform(o, serializedValue);
    }

    protected Object readTransform(Object o, Object serializedValue)
        throws IllegalArgumentException, IllegalAccessException {
      return this.owner.getOwner().readTransform(getField(), o.getClass(), serializedValue);
    }

    protected void handleException(boolean serialization, Object obj, Exception ex) {
      AutoSerializableManager.handleException(ex, serialization, getName(), obj);
    }

    protected int getInt(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getInt(o);
    }

    protected void setInt(Object o, int v) throws IllegalArgumentException, IllegalAccessException {
      this.field.setInt(o, v);
    }

    protected boolean getBoolean(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getBoolean(o);
    }

    protected void setBoolean(Object o, boolean v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setBoolean(o, v);
    }

    protected byte getByte(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getByte(o);
    }

    protected void setByte(Object o, byte v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setByte(o, v);
    }

    protected short getShort(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getShort(o);
    }

    protected void setShort(Object o, short v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setShort(o, v);
    }

    protected char getChar(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getChar(o);
    }

    protected void setChar(Object o, char v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setChar(o, v);
    }

    protected long getLong(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getLong(o);
    }

    protected void setLong(Object o, long v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setLong(o, v);
    }

    protected float getFloat(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getFloat(o);
    }

    protected void setFloat(Object o, float v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setFloat(o, v);
    }

    protected double getDouble(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getDouble(o);
    }

    protected void setDouble(Object o, double v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setDouble(o, v);
    }

    protected Object getObject(Object o) throws IllegalArgumentException, IllegalAccessException {
      return this.field.getObject(o);
    }

    protected void setObject(Object o, Object v)
        throws IllegalArgumentException, IllegalAccessException {
      this.field.setObject(o, v);
    }

    public boolean isIdentityField() {
      return this.isIdentityField;
    }

    @Override
    public String toString() {
      return this.fieldName + ": " + field.toString();
    }
  }

  public static class IntField extends PdxFieldWrapper {
    public IntField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeInt(getInt(obj));
        } else {
          writer.writeInt(getName(), getInt(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeInt((Integer) newValue);
      } else {
        writer.writeInt(getName(), (Integer) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readInt(pf)));
          } else {
            setInt(obj, reader.readInt(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readInt()));
        } else {
          setInt(obj, reader.readInt());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ByteField extends PdxFieldWrapper {
    public ByteField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeByte(getByte(obj));
        } else {
          writer.writeByte(getName(), getByte(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeByte((Byte) newValue);
      } else {
        writer.writeByte(getName(), (Byte) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readByte(pf)));
          } else {
            setByte(obj, reader.readByte(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readByte()));
        } else {
          setByte(obj, reader.readByte());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class LongField extends PdxFieldWrapper {
    public LongField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeLong(getLong(obj));
        } else {
          writer.writeLong(getName(), getLong(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeLong((Long) newValue);
      } else {
        writer.writeLong(getName(), (Long) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readLong(pf)));
          } else {
            setLong(obj, reader.readLong(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readLong()));
        } else {
          setLong(obj, reader.readLong());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class BooleanField extends PdxFieldWrapper {
    public BooleanField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeBoolean(getBoolean(obj));
        } else {
          writer.writeBoolean(getName(), getBoolean(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeBoolean((Boolean) newValue);
      } else {
        writer.writeBoolean(getName(), (Boolean) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readBoolean(pf)));
          } else {
            setBoolean(obj, reader.readBoolean(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readBoolean()));
        } else {
          setBoolean(obj, reader.readBoolean());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class CharField extends PdxFieldWrapper {
    public CharField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeChar(getChar(obj));
        } else {
          writer.writeChar(getName(), getChar(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeChar((Character) newValue);
      } else {
        writer.writeChar(getName(), (Character) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readChar(pf)));
          } else {
            setChar(obj, reader.readChar(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readChar()));
        } else {
          setChar(obj, reader.readChar());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ShortField extends PdxFieldWrapper {
    public ShortField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeShort(getShort(obj));
        } else {
          writer.writeShort(getName(), getShort(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeShort((Short) newValue);
      } else {
        writer.writeShort(getName(), (Short) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readShort(pf)));
          } else {
            setShort(obj, reader.readShort(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readShort()));
        } else {
          setShort(obj, reader.readShort());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class FloatField extends PdxFieldWrapper {
    public FloatField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeFloat(getFloat(obj));
        } else {
          writer.writeFloat(getName(), getFloat(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeFloat((Float) newValue);
      } else {
        writer.writeFloat(getName(), (Float) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readFloat(pf)));
          } else {
            setFloat(obj, reader.readFloat(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readFloat()));
        } else {
          setFloat(obj, reader.readFloat());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class DoubleField extends PdxFieldWrapper {
    public DoubleField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        if (optimizeWrite) {
          writer.writeDouble(getDouble(obj));
        } else {
          writer.writeDouble(getName(), getDouble(obj));
        }
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeDouble((Double) newValue);
      } else {
        writer.writeDouble(getName(), (Double) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          if (transform()) {
            setObject(obj, readTransform(obj, reader.readDouble(pf)));
          } else {
            setDouble(obj, reader.readDouble(pf));
          }
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        if (transform()) {
          setObject(obj, readTransform(obj, reader.readDouble()));
        } else {
          setDouble(obj, reader.readDouble());
        }
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ObjectField extends PdxFieldWrapper {
    public ObjectField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeObject(newValue, getCheckPortability());
      } else {
        writer.writeObject(getName(), newValue, getCheckPortability());
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readObject(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readObject()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class StringField extends PdxFieldWrapper {
    public StringField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeString((String) newValue);
      } else {
        writer.writeString(getName(), (String) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readString(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readString()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class DateField extends PdxFieldWrapper {
    public DateField(AutoSerializableManager owner, Field f, String name, boolean transformValue,
        boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeDate((Date) newValue);
      } else {
        writer.writeDate(getName(), (Date) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readDate(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readDate()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ByteArrayField extends PdxFieldWrapper {
    public ByteArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeByteArray((byte[]) newValue);
      } else {
        writer.writeByteArray(getName(), (byte[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readByteArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readByteArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class BooleanArrayField extends PdxFieldWrapper {
    public BooleanArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeBooleanArray((boolean[]) newValue);
      } else {
        writer.writeBooleanArray(getName(), (boolean[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readBooleanArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readBooleanArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ShortArrayField extends PdxFieldWrapper {
    public ShortArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeShortArray((short[]) newValue);
      } else {
        writer.writeShortArray(getName(), (short[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readShortArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readShortArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class CharArrayField extends PdxFieldWrapper {
    public CharArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeCharArray((char[]) newValue);
      } else {
        writer.writeCharArray(getName(), (char[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readCharArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readCharArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class IntArrayField extends PdxFieldWrapper {
    public IntArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeIntArray((int[]) newValue);
      } else {
        writer.writeIntArray(getName(), (int[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readIntArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readIntArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class LongArrayField extends PdxFieldWrapper {
    public LongArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeLongArray((long[]) newValue);
      } else {
        writer.writeLongArray(getName(), (long[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readLongArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readLongArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class FloatArrayField extends PdxFieldWrapper {
    public FloatArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeFloatArray((float[]) newValue);
      } else {
        writer.writeFloatArray(getName(), (float[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readFloatArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readFloatArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class DoubleArrayField extends PdxFieldWrapper {
    public DoubleArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeDoubleArray((double[]) newValue);
      } else {
        writer.writeDoubleArray(getName(), (double[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readDoubleArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readDoubleArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class StringArrayField extends PdxFieldWrapper {
    public StringArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeStringArray((String[]) newValue);
      } else {
        writer.writeStringArray(getName(), (String[]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readStringArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readStringArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ByteArrayArrayField extends PdxFieldWrapper {
    public ByteArrayArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeArrayOfByteArrays((byte[][]) newValue);
      } else {
        writer.writeArrayOfByteArrays(getName(), (byte[][]) newValue);
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readArrayOfByteArrays(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readArrayOfByteArrays()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }
  public static class ObjectArrayField extends PdxFieldWrapper {
    public ObjectArrayField(AutoSerializableManager owner, Field f, String name,
        boolean transformValue, boolean isIdentityField) {
      super(owner, f, name, transformValue, isIdentityField);
    }

    @Override
    public void serialize(PdxWriterImpl writer, Object obj, boolean optimizeWrite) {
      try {
        serializeValue(writer, getObject(obj), optimizeWrite);
      } catch (Exception ex) {
        handleException(true, obj, ex);
      }
    }

    @Override
    public void serializeValue(PdxWriterImpl writer, Object newValue, boolean optimizeWrite) {
      if (optimizeWrite) {
        writer.writeObjectArray((Object[]) newValue, getCheckPortability());
      } else {
        writer.writeObjectArray(getName(), (Object[]) newValue, getCheckPortability());
      }
    }

    @Override
    public void deserialize(InternalPdxReader reader, Object obj) {
      PdxField pf = reader.getPdxField(getName());
      if (pf != null) {
        try {
          setObject(obj, readTransformIf(obj, reader.readObjectArray(pf)));
        } catch (Exception ex) {
          handleException(false, obj, ex);
        }
      }
    }

    @Override
    public void orderedDeserialize(InternalPdxReader reader, Object obj) {
      try {
        setObject(obj, readTransformIf(obj, reader.readObjectArray()));
      } catch (Exception ex) {
        handleException(false, obj, ex);
      }
    }
  }

  /**
   * Given an object, use its class to determine which fields are to be used when (de)serializing.
   *
   * @param obj the object whose class we're interested in
   * @return a list of fields to be used when this object's class is (de)serialized
   */
  public List<PdxFieldWrapper> getFields(Object obj) {
    return getFields(obj.getClass());
  }

  /**
   * Using the given PdxWriter, write out the relevant fields for the object instance passed in.
   *
   * @param writer the <code>PdxWriter</code> to use when writing the object
   * @param obj the object to serialize
   * @return <code>true</code> if the object was serialized, <code>false</code> otherwise
   */
  public boolean writeData(PdxWriter writer, Object obj) {
    if (isRelevant(obj.getClass())) {
      writeData(writer, obj, getClassInfo(obj.getClass()));
      return true;
    }
    return false;
  }

  private static void handleException(Exception ex, boolean serialization, String fieldName,
      Object obj) {
    if (ex instanceof CancelException) {
      // fix for bug 43936
      throw (CancelException) ex;
    } else if (ex instanceof NonPortableClassException) {
      throw (NonPortableClassException) ex;
    } else {
      throw new PdxSerializationException((serialization ? "Serialization" : "Deserialization")
          + " error on field " + fieldName + " for class " + obj.getClass().getName(), ex);
    }
  }

  /**
   * Using the given PdxWriter, write out the fields which have been passed in.
   *
   * @param writer the <code>PdxWriter</code> to use when writing the object
   * @param obj the object to serialize
   * @param autoClassInfo a <code>List</code> of <code>Field</code>s which are to be written out
   */
  public void writeData(PdxWriter writer, Object obj, AutoClassInfo autoClassInfo) {
    PdxWriterImpl w = (PdxWriterImpl) writer;
    boolean optimizeFieldWrites = false;
    if (autoClassInfo.getSerializedType() != null) {
      // check to see if we have unread data for this instance
      if (w.initUnreadData() == null) {
        // we don't so we can optimize the field writes since
        // we will write them in the correct order
        optimizeFieldWrites = true;
      }
    }
    for (PdxFieldWrapper f : autoClassInfo.getFields()) {
      // System.out.println("DEBUG writing field=" + f.getField().getName() + " offset=" +
      // ((PdxWriterImpl)writer).position());
      if (f.transform()) {
        try {
          Object newValue =
              getOwner().writeTransform(f.getField(), obj.getClass(), f.getObject(obj));
          f.serializeValue(w, newValue, optimizeFieldWrites);
        } catch (Exception ex) {
          f.handleException(true, obj, ex);
        }
      } else {
        f.serialize(w, obj, optimizeFieldWrites);
      }
      if (f.isIdentityField() && w.definingNewPdxType()) {
        try {
          w.markIdentityField(f.getName());
        } catch (Exception ex) {
          handleException(ex, true, f.getName(), obj);
        }
      }
    }
    if (autoClassInfo.getSerializedType() == null) {
      autoClassInfo.setSerializedType(w.getAutoPdxType());
    }
  }

  private static final boolean USE_CONSTRUCTOR =
      !Boolean.getBoolean(DistributionConfig.GEMFIRE_PREFIX + "autopdx.ignoreConstructor");

  /**
   * Using the given PdxReader, recreate the given object.
   *
   * @param reader the <code>PdxReader</code> to use when reading the object
   * @param clazz the class of the object to re-create
   */
  public Object readData(PdxReader reader, Class<?> clazz) {
    Object result = null;
    if (isRelevant(clazz)) {
      AutoClassInfo ci = getClassInfo(clazz);
      result = ci.newInstance(clazz);
      InternalPdxReader ri = (InternalPdxReader) reader;
      PdxType pt = ri.getPdxType();
      if (ci.matchesPdxType(pt)) {
        pt.setAutoInfo(ci);
        ri.orderedDeserialize(result, ci);
      } else {
        for (PdxFieldWrapper f : ci.getFields()) {
          f.deserialize(ri, result);
        }
      }
    }
    return result;
  }

  /**
   * Add a new class pattern / identity-field pattern tuple
   *
   * @param classPattern the class pattern
   * @param fieldPattern the pattern to identify a field as an identity field within the given class
   *        pattern
   */
  public void addIdentityPattern(String classPattern, String fieldPattern) {
    identityPatterns.add(new String[] {classPattern, fieldPattern});
  }

  /**
   * Return the identity patterns. The patterns are returned as a <code>List</code> of
   * <code>String</code> arrays of size 2 - essentially a tuple of the form
   *
   * <pre>
   *   (classPattern, identityPattern)
   * </pre>
   *
   * @return the identity patterns
   */
  public List<String[]> getIdentityPatterns() {
    return identityPatterns;
  }

  /**
   * Add a new class pattern / exclude-field pattern tuple
   *
   * @param classPattern the class pattern
   * @param fieldPattern the pattern to exclude a field from serialization within the given class
   *        pattern
   */
  public void addExcludePattern(String classPattern, String fieldPattern) {
    excludePatterns.add(new String[] {classPattern, fieldPattern});
  }

  /**
   * Return the exclude patterns. The patterns are returned as a <code>List</code> of
   * <code>String</code> arrays of size 2 - essentially a tuple of the form
   *
   * <pre>
   *   (classPattern, excludePattern)
   * </pre>
   *
   * @return the exclude patterns
   */
  public List<String[]> getExcludePatterns() {
    return excludePatterns;
  }

  /*
   * Helper method which determines whether a given field matches a set of class/field patterns.
   *
   * @param field the <code>Field</code> to consider
   *
   * @param field the className which references this field
   *
   * @param matches a map containing the
   *
   */
  private boolean fieldMatches(Field field, String className, List<String[]> matches) {
    String fieldName = field.getName();

    for (String[] e : matches) {
      if (className.matches(e[0]) && fieldName.matches(e[1])) {
        return true;
      }
    }

    return false;
  }

  /**
   * Holds meta information about a class that we have auto serialized.
   *
   */
  public static class AutoClassInfo {
    private final WeakReference<Class<?>> clazzRef;
    /**
     * The fields that describe the class
     */
    private final List<PdxFieldWrapper> fields;
    /**
     * The pdxType ids that we are known to exactly match.
     */
    private final Set<Integer> matchingPdxIds = new CopyOnWriteArraySet<Integer>();
    /**
     * The pdxType ids that do not exactly match our class. Either their field order differs it they
     * have extra or missing fields.
     */
    private final Set<Integer> mismatchingPdxIds = new CopyOnWriteArraySet<Integer>();

    /**
     * The PdxType created by the first serialization by the auto serializer.
     */
    private PdxType serializedType = null;

    public AutoClassInfo(Class<?> clazz, List<PdxFieldWrapper> fields) {
      this.clazzRef = new WeakReference<Class<?>>(clazz);
      this.fields = fields;
    }

    public String toFormattedString() {
      StringBuffer sb = new StringBuffer();
      boolean first = true;
      for (Object o : this.fields) {
        if (first) {
          first = false;
          sb.append('\n');
        }
        sb.append("    ").append(o).append('\n');
      }
      return sb.toString();
    }

    public Object newInstance(Class<?> clazz) {
      Object result;
      try {
        if (unsafe != null && !USE_CONSTRUCTOR) {
          result = unsafe.allocateInstance(clazz);
        } else {
          result = clazz.newInstance();
        }
      } catch (Exception ex) {
        throw new PdxSerializationException(
            String.format("Could not create an instance of a class %s",
                clazz.getName()),
            ex);
      }
      return result;
    }

    public void setSerializedType(PdxType v) {
      this.serializedType = v;
    }

    public PdxType getSerializedType() {
      return this.serializedType;
    }

    public Class<?> getInfoClass() {
      return this.clazzRef.get();
    }

    public List<PdxFieldWrapper> getFields() {
      return this.fields;
    }

    public boolean matchesPdxType(PdxType t) {
      Integer pdxTypeId = Integer.valueOf(t.getTypeId());
      if (this.matchingPdxIds.contains(pdxTypeId)) {
        return true;
      } else if (this.mismatchingPdxIds.contains(pdxTypeId)) {
        return false;
      } else if (checkForMatch(t)) {
        this.matchingPdxIds.add(pdxTypeId);
        return true;
      } else {
        this.mismatchingPdxIds.add(pdxTypeId);
        return false;
      }
    }

    private boolean checkForMatch(PdxType t) {
      if (this.fields.size() != t.getUndeletedFieldCount()) {
        return false;
      }
      Iterator<PdxField> pdxIt = t.getFields().iterator();
      for (PdxFieldWrapper f : this.fields) {
        PdxField pdxF = pdxIt.next();
        if (pdxF.isDeleted()) {
          return false; // If the type has a deleted field then we can't do ordered deserialization
                        // because we need to skip over the deleted field's bytes.
        }
        if (!f.getName().equals(pdxF.getFieldName())) {
          return false;
        }
        if (!FieldType.get(f.getField().getType()).equals(pdxF.getFieldType())) {
          return false;
        }
      }
      return true;
    }

    @Override
    public String toString() {
      return "AutoClassInfo [fields=" + fields + "]";
    }
  }

  public void init(Properties props) {
    resetAll();
    if (props != null) {
      Enumeration<?> it = props.propertyNames();
      while (it.hasMoreElements()) {
        Object o = it.nextElement();
        if (o instanceof String) {
          String key = (String) o;
          if (INIT_CLASSES_PARAM.equals(key)) {
            String propValue = props.getProperty(INIT_CLASSES_PARAM);
            if (propValue != null) {
              processInitParams(propValue);
            }
          } else if (INIT_CHECK_PORTABILITY_PARAM.equals(key)) {
            String propValue = props.getProperty(INIT_CHECK_PORTABILITY_PARAM);
            if (propValue != null) {
              setCheckPortability(Boolean.parseBoolean(propValue));
            }
          } else if (NO_HARDCODED_EXCLUDES_PARAM.equals(key)) {
            if (props.getProperty(NO_HARDCODED_EXCLUDES_PARAM) != null) {
              noHardcodedExcludes = true;
            }
          } else {
            throw new IllegalArgumentException(
                "ReflectionBasedAutoSerializer: unknown init property \"" + key + "\"");
          }
        } else {
          throw new IllegalArgumentException(
              "ReflectionBasedAutoSerializer: unknown non-String init property \"" + o + "\"");
        }
      }
    }
  }

  public Properties getConfig() {
    Properties props = new Properties();
    if (classPatterns.isEmpty()) {
      return props;
    }

    StringBuilder sb = new StringBuilder();
    // This is so that we can exclude duplicates
    // LinkedHashSet is used to preserve the order of classPatterns. See bug 52286.
    Set<String> tmp = new LinkedHashSet<String>();
    for (Pattern p : classPatterns) {
      tmp.add(p.pattern());
    }
    for (Iterator<String> i = tmp.iterator(); i.hasNext();) {
      String s = i.next();
      sb.append(s);
      if (i.hasNext()) {
        sb.append(", ");
      }
    }

    if (getIdentityPatterns().size() > 0) {
      sb.append(", ");
      for (Iterator<String[]> i = getIdentityPatterns().iterator(); i.hasNext();) {
        String[] s = i.next();
        sb.append(s[0]).append("#" + OPT_IDENTITY + "=").append(s[1]);
        if (i.hasNext()) {
          sb.append(", ");
        }
      }
    }

    if (getExcludePatterns().size() > 0) {
      sb.append(", ");
      for (Iterator<String[]> i = getExcludePatterns().iterator(); i.hasNext();) {
        String[] s = i.next();
        sb.append(s[0]).append("#" + OPT_EXCLUDE + "=").append(s[1]);
        if (i.hasNext()) {
          sb.append(", ");
        }
      }
    }

    props.put(INIT_CLASSES_PARAM, sb.toString());

    if (getCheckPortability()) {
      props.put(INIT_CHECK_PORTABILITY_PARAM, "true");
    }

    return props;
  }

  public void reconfigure(boolean b, String... patterns) {
    resetAll();
    setCheckPortability(b);
    for (String c : patterns) {
      processInitParams(c);
    }
  }

  private void processInitParams(String value) {
    String identityPattern;
    String excludePattern;

    for (String s : value.split("[, ]+")) {
      if (s.length() > 0) {
        // Let's check for any additional embedded params...
        String[] split = s.split("#");
        for (int i = 1; i < split.length; i++) {
          identityPattern = null;
          excludePattern = null;

          String[] paramVals = split[i].split("=");
          if (paramVals.length != 2) {
            throw new IllegalArgumentException(
                "Unable to correctly process auto serialization init value: " + value);
          }
          if (OPT_IDENTITY.equalsIgnoreCase(paramVals[0])) {
            identityPattern = paramVals[1];
          } else if (OPT_EXCLUDE.equalsIgnoreCase(paramVals[0])) {
            excludePattern = paramVals[1];
          } else {
            throw new IllegalArgumentException(
                "Unable to correctly process auto serialization init value: " + value);
          }
          if (identityPattern != null) {
            addIdentityPattern(split[0], identityPattern);
          }
          if (excludePattern != null) {
            addExcludePattern(split[0], excludePattern);
          }
        }
        classPatterns.add(Pattern.compile(split[0]));
      }
    }
  }

  private RegionService cache;

  public RegionService getRegionService() {
    return this.cache;
  }

  public void setRegionService(RegionService rs) {
    this.cache = rs;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + (checkPortability ? 1231 : 1237);
    result = prime * result + ((classPatterns == null) ? 0 : classPatterns.hashCode());
    result = prime * result + ((excludePatterns == null) ? 0 : excludePatterns.hashCode());
    result = prime * result + ((identityPatterns == null) ? 0 : identityPatterns.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj)
      return true;
    if (obj == null)
      return false;
    if (getClass() != obj.getClass())
      return false;
    AutoSerializableManager other = (AutoSerializableManager) obj;
    if (checkPortability != other.checkPortability)
      return false;
    if (classPatterns == null) {
      if (other.classPatterns != null)
        return false;
    } else if (!classPatterns.equals(other.classPatterns))
      return false;
    if (excludePatterns == null) {
      if (other.excludePatterns != null)
        return false;
    } else if (!excludePatterns.equals(other.excludePatterns))
      return false;
    if (identityPatterns == null) {
      if (other.identityPatterns != null)
        return false;
    } else if (!identityPatterns.equals(other.identityPatterns))
      return false;
    return true;
  }
}
