You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by de...@apache.org on 2009/12/11 01:06:22 UTC

svn commit: r889476 [2/5] - in /openjpa/branches/1.1.x: openjpa-kernel/src/main/java/org/apache/openjpa/meta/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/inheritance/mappedsuperclass/idclass/ openjpa-persistence/src/main/java/...

Modified: openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java?rev=889476&r1=889475&r2=889476&view=diff
==============================================================================
--- openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java (original)
+++ openjpa/branches/1.1.x/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java Fri Dec 11 00:06:21 2009
@@ -1,2354 +1,2379 @@
-/*
- * 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.openjpa.meta;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.datacache.DataCache;
-import org.apache.openjpa.enhance.PCRegistry;
-import org.apache.openjpa.enhance.Reflection;
-import org.apache.openjpa.enhance.PersistenceCapable;
-import org.apache.openjpa.lib.log.Log;
-import org.apache.openjpa.lib.meta.SourceTracker;
-import org.apache.openjpa.lib.util.J2DoPrivHelper;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.lib.xml.Commentable;
-import org.apache.openjpa.util.BigDecimalId;
-import org.apache.openjpa.util.BigIntegerId;
-import org.apache.openjpa.util.ByteId;
-import org.apache.openjpa.util.CharId;
-import org.apache.openjpa.util.DateId;
-import org.apache.openjpa.util.DoubleId;
-import org.apache.openjpa.util.FloatId;
-import org.apache.openjpa.util.GeneralException;
-import org.apache.openjpa.util.IntId;
-import org.apache.openjpa.util.InternalException;
-import org.apache.openjpa.util.LongId;
-import org.apache.openjpa.util.MetaDataException;
-import org.apache.openjpa.util.ObjectId;
-import org.apache.openjpa.util.OpenJPAId;
-import org.apache.openjpa.util.ShortId;
-import org.apache.openjpa.util.StringId;
-import org.apache.openjpa.util.UnsupportedException;
-import org.apache.openjpa.util.ImplHelper;
-import serp.util.Strings;
-
-/**
- * Contains metadata about a persistent type.
- * This metadata is available both at enhancement time and runtime.
- *  Note that this class employs aggressive caching, and therefore it is
- * important to finalize the configuration of field metadatas before invoking
- * methods that depend on that configuration, such as
- * {@link #getPrimaryKeyFields}.
- *
- * @author Abe White
- */
-public class ClassMetaData
-    extends Extensions
-    implements Comparable, SourceTracker, MetaDataContext, MetaDataModes,
-    Commentable {
-
-    /**
-     * Unkonwn identity type.
-     */
-    public static final int ID_UNKNOWN = 0;
-
-    /**
-     * Datastore identity type.
-     */
-    public static final int ID_DATASTORE = 1;
-
-    /**
-     * Application identity type.
-     */
-    public static final int ID_APPLICATION = 2;
-
-    /**
-     * Unknown access type.
-     */
-    public static final int ACCESS_UNKNOWN = 0;
-
-    /**
-     * Persistent attributes are accessed via direct field access. Bit flag.
-     */
-    public static final int ACCESS_FIELD = 2 << 0;
-
-    /**
-     * Persistent attributes are accessed via setters and getters. Bit flag.
-     */
-    public static final int ACCESS_PROPERTY = 2 << 1;
-
-    /**
-     * Value for using a synthetic detached state field, which is the default.
-     */
-    public static final String SYNTHETIC = "`syn";
-
-    protected static final String DEFAULT_STRING = "`";
-
-    private static final Localizer _loc = Localizer.forPackage
-        (ClassMetaData.class);
-
-    private static final FetchGroup[] EMPTY_FETCH_GROUP_ARRAY
-        = new FetchGroup[0];
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
-
-    private MetaDataRepository _repos;
-    private transient ClassLoader _loader = null;
-
-    private final ValueMetaData _owner;
-    private final LifecycleMetaData _lifeMeta = new LifecycleMetaData(this);
-    private File _srcFile = null;
-    private int _srcType = SRC_OTHER;
-    private String[] _comments = null;
-    private int _listIndex = -1;
-    private int _srcMode = MODE_META | MODE_MAPPING;
-    private int _resMode = MODE_NONE;
-
-    private Class _type = Object.class;
-    private final Map _fieldMap = new TreeMap();
-    private Map _supFieldMap = null;
-    private boolean _defSupFields = false;
-    private Collection _staticFields = null;
-    private int[] _fieldDataTable = null;
-    private Map _fgMap = null;
-
-    ////////////////////////////////////////////////////////////////////
-    // Note: if you add additional state, make sure to add it to copy()
-    ////////////////////////////////////////////////////////////////////
-
-    private Class _objectId = null;
-    private Boolean _objectIdShared = null;
-    private Boolean _openjpaId = null;
-    private Boolean _extent = null;
-    private Boolean _embedded = null;
-    private Boolean _interface = null;
-    private Class _impl = null;
-    private List _interfaces = null;
-    private final Map _ifaceMap = new HashMap();
-    private int _identity = ID_UNKNOWN;
-    private int _idStrategy = ValueStrategies.NONE;
-    private int _accessType = ACCESS_UNKNOWN;
-
-    private String _seqName = DEFAULT_STRING;
-    private SequenceMetaData _seqMeta = null;
-    private String _cacheName = DEFAULT_STRING;
-    private int _cacheTimeout = Integer.MIN_VALUE;
-    private Boolean _detachable = null;
-    private String _detachState = DEFAULT_STRING;
-    private String _alias = null;
-    private int _versionIdx = Integer.MIN_VALUE;
-
-    private Class _super = null;
-    private ClassMetaData _superMeta = null;
-    private Class[] _subs = null;
-    private ClassMetaData[] _subMetas = null;
-    private ClassMetaData[] _mapSubMetas = null;
-
-    private FieldMetaData[] _fields = null;
-    private FieldMetaData[] _unmgdFields = null;
-    private FieldMetaData[] _allFields = null;
-    private FieldMetaData[] _allPKFields = null;
-    private FieldMetaData[] _allDFGFields = null;
-    private FieldMetaData[] _definedFields = null;
-    private FieldMetaData[] _listingFields = null;
-    private FieldMetaData[] _allListingFields = null;
-    private FetchGroup[] _fgs = null;
-    private FetchGroup[] _customFGs = null;
-    private boolean _intercepting = false;
-
-    /**
-     * Constructor. Supply described type and repository.
-     */
-    protected ClassMetaData(Class type, MetaDataRepository repos) {
-        _repos = repos;
-        _owner = null;
-        setDescribedType(type);
-    }
-
-    /**
-     * Embedded constructor. Supply embedding value.
-     */
-    protected ClassMetaData(ValueMetaData owner) {
-        _owner = owner;
-        _repos = owner.getRepository();
-        setEnvClassLoader(owner.getFieldMetaData().getDefiningMetaData().
-            getEnvClassLoader());
-    }
-
-    /**
-     * Return the owning repository.
-     */
-    public MetaDataRepository getRepository() {
-        return _repos;
-    }
-
-    /**
-     * If this metadata is for an embedded object, returning the owning value.
-     */
-    public ValueMetaData getEmbeddingMetaData() {
-        return _owner;
-    }
-
-    /**
-     * The persistence capable class described by this metadata.
-     */
-    public Class getDescribedType() {
-        return _type;
-    }
-
-    /**
-     * Set the class descibed by this metadata. The type may be reset when
-     * an embedded value changes its declared type.
-     */
-    protected void setDescribedType(Class type) {
-        if (type.getSuperclass() != null && "java.lang.Enum".equals
-            (type.getSuperclass().getName()))
-            throw new MetaDataException(_loc.get("enum", type));
-        _type = type;
-        if (PersistenceCapable.class.isAssignableFrom(type))
-            setIntercepting(true);
-    }
-
-    /**
-     * The environmental loader used when loading this metadata.
-     * The class metadata should use this loader when loading metadata for
-     * its superclass and field types.
-     */
-    public ClassLoader getEnvClassLoader() {
-        return _loader;
-    }
-
-    /**
-     * The class environmental loader used when loading this metadata.
-     * The class metadata should use this loader when loading metadata for
-     * its superclass and field types.
-     */
-    public void setEnvClassLoader(ClassLoader loader) {
-        _loader = loader;
-    }
-
-    /**
-     * The persistence capable superclass of the described type.
-     */
-    public Class getPCSuperclass() {
-        return _super;
-    }
-
-    /**
-     * The persistence capable superclass of the described type.
-     */
-    public void setPCSuperclass(Class pc) {
-        clearAllFieldCache();
-        _super = pc;
-    }
-
-    /**
-     * The metadata for this class' superclass.
-     */
-    public ClassMetaData getPCSuperclassMetaData() {
-        if (_superMeta == null && _super != null) {
-            if (_owner != null) {
-                _superMeta = _repos.newEmbeddedClassMetaData(_owner);
-                _superMeta.setDescribedType(_super);
-            } else
-                _superMeta = _repos.getMetaData(_super, _loader, true);
-        }
-        return _superMeta;
-    }
-
-    /**
-     * The metadata for this class' superclass.
-     */
-    public void setPCSuperclassMetaData(ClassMetaData meta) {
-        clearAllFieldCache();
-        _superMeta = meta;
-        if (meta != null)
-            setPCSuperclass(meta.getDescribedType());
-    }
-
-    /**
-     * Whether this class is mapped to the datastore. By default, only
-     * returns false if class is embedded-only, but subclasses might override
-     * to allow unmapped other types.
-     */
-    public boolean isMapped() {
-        return _embedded != Boolean.TRUE;
-    }
-
-    /**
-     * Return the closest mapped superclass.
-     */
-    public ClassMetaData getMappedPCSuperclassMetaData() {
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup == null || sup.isMapped())
-            return sup;
-        return sup.getMappedPCSuperclassMetaData();
-    }
-
-    /**
-     * Return the known persistence capable subclasses of the described type,
-     * or empty array if none or if this is embedded metadata.
-     */
-    public Class[] getPCSubclasses() {
-        if (_owner != null)
-            return _repos.EMPTY_CLASSES;
-
-        _repos.processRegisteredClasses(_loader);
-        if (_subs == null) {
-            Collection subs = _repos.getPCSubclasses(_type);
-            _subs = (Class[]) subs.toArray(new Class[subs.size()]);
-        }
-        return _subs;
-    }
-
-    /**
-     * Return the metadata for the known persistence capable subclasses of
-     * the described type, or empty array if none or if this is embedded
-     * metadata.
-     */
-    public ClassMetaData[] getPCSubclassMetaDatas() {
-        if (_owner != null)
-            return _repos.EMPTY_METAS;
-
-        Class[] subs = getPCSubclasses(); // checks for new
-        if (_subMetas == null) {
-            if (subs.length == 0)
-                _subMetas = _repos.EMPTY_METAS;
-            else {
-                ClassMetaData[] metas = _repos.newClassMetaDataArray
-                    (subs.length);
-                for (int i = 0; i < subs.length; i++)
-                    metas[i] = _repos.getMetaData(subs[i], _loader, true);
-                _subMetas = metas;
-            }
-        }
-        return _subMetas;
-    }
-
-    /**
-     * Return all mapped subclasses.
-     */
-    public ClassMetaData[] getMappedPCSubclassMetaDatas() {
-        if (_owner != null)
-            return _repos.EMPTY_METAS;
-
-        ClassMetaData[] subs = getPCSubclassMetaDatas(); // checks for new
-        if (_mapSubMetas == null) {
-            if (subs.length == 0)
-                _mapSubMetas = subs;
-            else {
-                List mapped = new ArrayList(subs.length);
-                for (int i = 0; i < subs.length; i++)
-                    if (subs[i].isMapped())
-                        mapped.add(subs[i]);
-                _mapSubMetas = (ClassMetaData[]) mapped.toArray
-                    (_repos.newClassMetaDataArray(mapped.size()));
-            }
-        }
-        return _mapSubMetas;
-    }
-
-    /**
-     * The type of identity being used. This will be one of:
-     * <ul>
-     * <li>{@link #ID_UNKNOWN}: unknown identity type</li>
-     * <li>{@link #ID_DATASTORE}: identity managed by the data store and
-     * independent	of the fields of the instance</li>
-     * <li>{@link #ID_APPLICATION}: identity managed by the application and
-     * defined by one or more fields of the instance</li>
-     * </ul> If unspecified, defaults to {@link #ID_DATASTORE} if there are no
-     * primary key fields, and {@link #ID_APPLICATION} otherwise.
-     */
-    public int getIdentityType() {
-        if (_identity == ID_UNKNOWN) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null && sup.getIdentityType() != ID_UNKNOWN)
-                _identity = sup.getIdentityType();
-            else if (getPrimaryKeyFields().length > 0)
-                _identity = ID_APPLICATION;
-            else if (isMapped())
-                _identity = ID_DATASTORE;
-            else
-                _identity = _repos.getMetaDataFactory().getDefaults().
-                    getDefaultIdentityType();
-        }
-        return _identity;
-    }
-
-    /**
-     * The type of identity being used. This will be one of:
-     * <ul>
-     * <li>{@link #ID_UNKNOWN}: unknown identity type</li>
-     * <li>{@link #ID_DATASTORE}: identity managed by the data store and
-     * independent	of the fields of the instance</li>
-     * <li>{@link #ID_APPLICATION}: identity managed by the application and
-     * defined by one or more fields of the instance</li>
-     * </ul> If unspecified, defaults to {@link #ID_DATASTORE} if there are no
-     * primary key fields, and {@link #ID_APPLICATION} otherwise.
-     */
-    public void setIdentityType(int type) {
-        _identity = type;
-        if (type != ID_APPLICATION) {
-            _objectId = null;
-            _openjpaId = null;
-        }
-    }
-
-    /**
-     * The metadata-specified class to use for the object ID.
-     */
-    public Class getObjectIdType() {
-        if (_objectId != null)
-            return _objectId;
-        if (getIdentityType() != ID_APPLICATION)
-            return null;
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup != null && sup.getIdentityType() != ID_UNKNOWN) {
-            _objectId = sup.getObjectIdType();
-            return _objectId;
-        }
-
-        // figure out openjpa identity type based on primary key field
-        FieldMetaData[] pks = getPrimaryKeyFields();
-        if (pks.length != 1)
-            return null;
-        switch (pks[0].getObjectIdFieldTypeCode()) {
-            case JavaTypes.BYTE:
-            case JavaTypes.BYTE_OBJ:
-                _objectId = ByteId.class;
-                break;
-            case JavaTypes.CHAR:
-            case JavaTypes.CHAR_OBJ:
-                _objectId = CharId.class;
-                break;
-            case JavaTypes.DOUBLE:
-            case JavaTypes.DOUBLE_OBJ:
-                _objectId = DoubleId.class;
-                break;
-            case JavaTypes.FLOAT:
-            case JavaTypes.FLOAT_OBJ:
-                _objectId = FloatId.class;
-                break;
-            case JavaTypes.INT:
-            case JavaTypes.INT_OBJ:
-                _objectId = IntId.class;
-                break;
-            case JavaTypes.LONG:
-            case JavaTypes.LONG_OBJ:
-                _objectId = LongId.class;
-                break;
-            case JavaTypes.SHORT:
-            case JavaTypes.SHORT_OBJ:
-                _objectId = ShortId.class;
-                break;
-            case JavaTypes.STRING:
-                _objectId = StringId.class;
-                break;
-            case JavaTypes.DATE:
-                _objectId = DateId.class;
-                break;
-            case JavaTypes.OID:
-            case JavaTypes.OBJECT:
-                _objectId = ObjectId.class;
-                break;
-            case JavaTypes.BIGDECIMAL:
-                _objectId = BigDecimalId.class;
-                break;
-            case JavaTypes.BIGINTEGER:
-                _objectId = BigIntegerId.class;
-                break;
-        }
-        return _objectId;
-    }
-
-    /**
-     * The metadata-specified class to use for the object ID.
-     */
-    public void setObjectIdType(Class cls, boolean shared) {
-        _objectId = null;
-        _openjpaId = null;
-        _objectIdShared = null;
-        if (cls != null) {
-            // don't let people assign OpenJPAId types; safer to calculate it
-            // ourselves
-            setIdentityType(ID_APPLICATION);
-            if (!OpenJPAId.class.isAssignableFrom(cls)) {
-                _objectId = cls;
-                _objectIdShared = (shared) ? Boolean.TRUE : Boolean.FALSE;
-            }
-        }
-    }
-
-    /**
-     * Whether this type uses an application identity class that is shared
-     * with other classes, and is therefore wrapped in an {@link ObjectId}.
-     */
-    public boolean isObjectIdTypeShared() {
-        if (_objectIdShared != null)
-            return _objectIdShared.booleanValue();
-        if (_super != null)
-            return getPCSuperclassMetaData().isObjectIdTypeShared();
-        return isOpenJPAIdentity();
-    }
-
-    /**
-     * Whether this type uses OpenJPA identity.
-     */
-    public boolean isOpenJPAIdentity() {
-        if (_openjpaId == null) {
-            Class cls = getObjectIdType();
-            if (cls == null)
-                return false;
-            _openjpaId = (OpenJPAId.class.isAssignableFrom(cls)) ? Boolean.TRUE
-                : Boolean.FALSE;
-        }
-        return _openjpaId.booleanValue();
-    }
-
-    /**
-     * The strategy to use for datastore identity generation.
-     * One of the constants from {@link ValueStrategies}.
-     */
-    public int getIdentityStrategy() {
-        if (getIdentityType() == ID_DATASTORE
-            && _idStrategy == ValueStrategies.NONE) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null && sup.getIdentityType() != ID_UNKNOWN)
-                _idStrategy = sup.getIdentityStrategy();
-            else
-                _idStrategy = ValueStrategies.NATIVE;
-        }
-        return _idStrategy;
-    }
-
-    /**
-     * The strategy to use for datastore identity generation.
-     * One of the constants from {@link ValueStrategies}.
-     */
-    public void setIdentityStrategy(int strategy) {
-        _idStrategy = strategy;
-        if (strategy != ValueStrategies.SEQUENCE)
-            setIdentitySequenceName(null);
-    }
-
-    /**
-     * The datastore identity sequence name, or null for none.
-     */
-    public String getIdentitySequenceName() {
-        if (DEFAULT_STRING.equals(_seqName)) {
-            if (_super != null)
-                _seqName = getPCSuperclassMetaData().getIdentitySequenceName();
-            else
-                _seqName = null;
-        }
-        return _seqName;
-    }
-
-    /**
-     * The datastore identity sequence name, or null for none.
-     */
-    public void setIdentitySequenceName(String seqName) {
-        _seqName = seqName;
-        _seqMeta = null;
-        if (seqName != null)
-            setIdentityStrategy(ValueStrategies.SEQUENCE);
-    }
-
-    /**
-     * Metadata for the datastore identity sequence.
-     */
-    public SequenceMetaData getIdentitySequenceMetaData() {
-        if (_seqMeta == null && getIdentitySequenceName() != null)
-            _seqMeta = _repos.getSequenceMetaData(this,
-                getIdentitySequenceName(), true);
-        return _seqMeta;
-    }
-
-    /**
-     * Information about lifecycle callbacks for this class.
-     */
-    public LifecycleMetaData getLifecycleMetaData() {
-        return _lifeMeta;
-    }
-
-    /**
-     * Returns the alias for the described type, or <code>null</code> if none
-     * has been set.
-     * 
-     * @see #setTypeAlias
-     */
-    public String getTypeAlias() {
-        if (_alias == null)
-            _alias = Strings.getClassName(_type);
-        return _alias;
-    }
-
-    /**
-     * Sets the alias for the described type. The alias can be
-     * any arbitrary string that the implementation can later use to
-     * refer to the class. Note that at runtime, only the alias
-     * computed when the persistent type was enhanced is used.
-     *
-     * @param alias the alias name to apply to the described type
-     */
-    public void setTypeAlias(String alias) {
-        _alias = alias;
-    }
-
-    /**
-     * The access type used by this class. Either {@link #ACCESS_FIELD}
-     * or {@link #ACCESS_PROPERTY}.
-     */
-    public int getAccessType() {
-        if (_accessType == ACCESS_UNKNOWN) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null)
-                return sup.getAccessType();
-            else {
-                return getRepository().getMetaDataFactory().
-                    getDefaults().getDefaultAccessType();
-            }
-        }
-        return _accessType;
-    }
-
-    /**
-     * The access type used by this class. Must be either
-     * {@link #ACCESS_FIELD} or {@link #ACCESS_PROPERTY}.
-     */
-    public void setAccessType(int type) {
-        _accessType = type;
-    }
-
-    /**
-     * Whether the type requires extent management.
-     */
-    public boolean getRequiresExtent() {
-        if (_owner != null || isEmbeddedOnly())
-            return false;
-
-        if (_extent == null) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null)
-                _extent = (sup.getRequiresExtent()) ? Boolean.TRUE
-                    : Boolean.FALSE;
-            else
-                _extent = Boolean.TRUE;
-        }
-        return _extent.booleanValue();
-    }
-
-    /**
-     * Whether the type requires extent management.
-     */
-    public void setRequiresExtent(boolean req) {
-        _extent = (req) ? Boolean.TRUE : Boolean.FALSE;
-    }
-
-    /**
-     * Whether the type can only be used as an embedded object.
-     */
-    public boolean isEmbeddedOnly() {
-        if (_embedded == null) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null)
-                _embedded = (sup.isEmbeddedOnly()) ? Boolean.TRUE
-                    : Boolean.FALSE;
-            else
-                _embedded = Boolean.FALSE;
-        }
-        return _embedded.booleanValue();
-    }
-
-    /**
-     * Whether the type can only be used as an embedded object.
-     */
-    public void setEmbeddedOnly(boolean embed) {
-        _embedded = (embed) ? Boolean.TRUE : Boolean.FALSE;
-    }
-
-    /**
-     * Whether the type's fields are actively intercepted, either by
-     * redefinition or enhancement.
-     */
-    public boolean isIntercepting() {
-        return _intercepting;
-    }
-
-    /**
-     * Whether the type's fields are actively intercepted, either by
-     * redefinition or enhancement.
-     */
-    public void setIntercepting(boolean intercepting) {
-        _intercepting = intercepting;
-    }
-
-    /**
-     * Whether the type is a managed interface.
-     */
-    public boolean isManagedInterface() {
-        if (!_type.isInterface())
-            return false;
-        return _interface == null ? false : _interface.booleanValue();
-    }
-
-    /**
-     * Whether the type is a managed interface
-     */
-    public void setManagedInterface(boolean managedInterface) {
-        if (!_type.isInterface())
-            throw new MetaDataException(_loc.get("not-interface", _type));
-        _interface = managedInterface ? Boolean.TRUE : Boolean.FALSE;
-
-        // managed interfaces always do proper interception; OpenJPA generates
-        // the implementations.
-        if (isManagedInterface())
-            setIntercepting(true);
-
-        // managed interfaces always use property access.
-        setAccessType(ACCESS_PROPERTY);
-    }
-
-    /**
-     * Return the managed interface implementor if any.
-     */
-    public Class getInterfaceImpl() {
-        return _impl;
-    }
-
-    /**
-     * Set the managed interface implementor class.
-     */
-    public void setInterfaceImpl(Class impl) {
-        _impl = impl;
-    }
-
-    /**
-     * Return all explicitly declared interfaces this class implements.
-     */
-    public Class[] getDeclaredInterfaces() {
-        if (_interfaces == null)
-            return MetaDataRepository.EMPTY_CLASSES;
-        return (Class[]) _interfaces.toArray(new Class[_interfaces.size()]);
-    }
-
-    /**
-     * Explicitly declare the given interface among the ones this
-     * class implements.
-     */
-    public void addDeclaredInterface(Class iface) {
-        if (iface == null || !iface.isInterface())
-            throw new MetaDataException(_loc.get("declare-non-interface",
-                this, iface));
-        if (_interfaces == null)
-            _interfaces = new ArrayList();
-        _interfaces.add(iface);
-    }
-
-    /**
-     * Remove the given interface from the declared list.
-     */
-    public boolean removeDeclaredInterface(Class iface) {
-        if (_interfaces == null)
-            return false;
-        return _interfaces.remove(iface);
-    }
-
-    /**
-     * Alias properties from the given interface during  queries to
-     * the local field.
-     */
-    public void setInterfacePropertyAlias(Class iface, String orig, 
-        String local) {
-        synchronized (_ifaceMap) {
-            Map fields = (Map) _ifaceMap.get(iface);
-            if (fields == null) {
-                fields = new HashMap();
-                _ifaceMap.put(iface, fields);
-            }
-            if (fields.containsKey(orig))
-                throw new MetaDataException(_loc.get("duplicate-iface-alias", 
-                    this, orig, local));
-            fields.put(orig, local);
-        }
-    }
-    
-    /**
-     * Get local field alias for the given interface property.
-     */
-    public String getInterfacePropertyAlias(Class iface, String orig) {
-        synchronized (_ifaceMap) {
-            Map fields = (Map) _ifaceMap.get(iface);
-            if (fields == null)
-                return null;
-            return (String) fields.get(orig);
-        }
-    }
-    
-    /**
-     * Return all aliases property named for the given interface.
-     */
-    public String[] getInterfaceAliasedProperties(Class iface) {
-        synchronized (_ifaceMap) {
-            Map fields = (Map) _ifaceMap.get(iface);
-            if (fields == null)
-                return EMPTY_STRING_ARRAY;
-            return (String[]) fields.keySet().toArray(
-                new String[fields.size()]);
-        }
-    }
-    
-    /**
-     * Return the number of fields that use impl or intermediate data, in
-     * order to create a compacted array for storage of said data.
-     */
-    public int getExtraFieldDataLength() {
-        int[] table = getExtraFieldDataTable();
-        for (int i = table.length - 1; i >= 0; i--)
-            if (table[i] != -1)
-                return table[i] + 1;
-        return 0;
-    }
-
-    /**
-     * Return the impl / intermediate field data index of the given field
-     * in the compacted array, or -1 if the field does not use extra data.
-     *
-     * @see #getExtraFieldDataLength
-     */
-    public int getExtraFieldDataIndex(int field) {
-        return getExtraFieldDataTable()[field];
-    }
-
-    /**
-     * Creates a table mapping each field index to its extra data index.
-     */
-    private int[] getExtraFieldDataTable() {
-        if (_fieldDataTable == null) {
-            FieldMetaData[] fmds = getFields();
-            int[] table = new int[fmds.length];
-            int idx = 0;
-            for (int i = 0; i < fmds.length; i++) {
-                if (fmds[i].usesIntermediate()
-                    || fmds[i].usesImplData() != Boolean.FALSE)
-                    table[i] = idx++;
-                else
-                    table[i] = -1;
-            }
-            _fieldDataTable = table;
-        }
-        return _fieldDataTable;
-    }
-
-    /**
-     * Return whether the given name represents a managed or static field of
-     * this class, including superclass fields.
-     */
-    public boolean isAccessibleField(String field) {
-        if (getDeclaredField(field) != null)
-            return true;
-        if (_staticFields == null) {
-            Field[] fields = (Field[]) AccessController.doPrivileged(
-                J2DoPrivHelper.getDeclaredFieldsAction(_type)); 
-            Set names = new HashSet((int) (fields.length * 1.33 + 1));
-            for (int i = 0; i < fields.length; i++)
-                if (Modifier.isStatic(fields[i].getModifiers()))
-                    names.add(fields[i].getName());
-            _staticFields = names;
-        }
-        if (_staticFields.contains(field))
-            return true;
-        if (_super != null)
-            return getPCSuperclassMetaData().isAccessibleField(field);
-        return false;
-    }
-
-    /**
-     * Return all field metadatas, including superclass fields.
-     */
-    public FieldMetaData[] getFields() {
-        if (_allFields == null) {
-            if (_super == null)
-                _allFields = getDeclaredFields();
-            else {
-                FieldMetaData[] fields = getDeclaredFields();
-                FieldMetaData[] supFields = getPCSuperclassMetaData().
-                    getFields();
-
-                FieldMetaData[] allFields = _repos.newFieldMetaDataArray
-                    (fields.length + supFields.length);
-                System.arraycopy(supFields, 0, allFields, 0, supFields.length);
-                replaceDefinedSuperclassFields(allFields, supFields.length);
-
-                for (int i = 0; i < fields.length; i++) {
-                    fields[i].setIndex(supFields.length + i);
-                    allFields[supFields.length + i] = fields[i];
-                }
-                _allFields = allFields;
-            }
-        }
-        return _allFields;
-    }
-
-    /**
-     * Replace superclass fields that we define with our version.
-     */
-    private void replaceDefinedSuperclassFields(FieldMetaData[] fields,
-        int len) {
-        if (_supFieldMap == null || !_defSupFields)
-            return;
-
-        // don't assume fields are in order; this method is used for
-        // listing order as well
-        FieldMetaData supField;
-        for (int i = 0; i < len; i++) {
-            supField = (FieldMetaData) _supFieldMap.get(fields[i].getName());
-            if (supField != null) {
-                fields[i] = supField;
-                supField.setIndex(i);
-            }
-        }
-    }
-
-    /**
-     * Return the superclass copy of the given field.
-     */
-    protected FieldMetaData getSuperclassField(FieldMetaData supField) {
-        ClassMetaData sm = getPCSuperclassMetaData();
-        FieldMetaData fmd = sm == null ? null : sm.getField(supField.getName());
-        if (fmd == null || fmd.getManagement() != fmd.MANAGE_PERSISTENT)
-            throw new MetaDataException(_loc.get("unmanaged-sup-field",
-                supField, this));
-        return fmd;
-    }
-
-    /**
-     * Return only the fields for this class, without superclass fields.
-     */
-    public FieldMetaData[] getDeclaredFields() {
-        if (_fields == null) {
-            List fields = new ArrayList(_fieldMap.size());
-            FieldMetaData fmd;
-            for (Iterator itr = _fieldMap.values().iterator(); itr.hasNext();) {
-                fmd = (FieldMetaData) itr.next();
-                if (fmd.getManagement() != FieldMetaData.MANAGE_NONE) {
-                    fmd.setDeclaredIndex(fields.size());
-                    fmd.setIndex(fmd.getDeclaredIndex());
-                    fields.add(fmd);
-                }
-            }
-            _fields = (FieldMetaData[]) fields.toArray
-                (_repos.newFieldMetaDataArray(fields.size()));
-        }
-        return _fields;
-    }
-
-    /**
-     * Return primary key fields, or empty array if none. The order
-     * in which the keys are returned will be the order in which
-     * the fields are declared, starting at the least-derived superclass
-     * and ending with the primary key fields of the most-derived subclass.
-     */
-    public FieldMetaData[] getPrimaryKeyFields() {
-        // check for pk fields even if not set to ID_APPLICATION so that
-        // app id tool sees them even when user doesn't declare app id
-        if (_allPKFields == null) {
-            FieldMetaData[] fields = getFields();
-            int num = 0;
-            for (int i = 0; i < fields.length; i++)
-                if (fields[i].isPrimaryKey())
-                    num++;
-
-            if (num == 0)
-                _allPKFields = _repos.EMPTY_FIELDS;
-            else {
-                FieldMetaData[] pks = _repos.newFieldMetaDataArray(num);
-                num = 0;
-                for (int i = 0; i < fields.length; i++) {
-                    if (fields[i].isPrimaryKey()) {
-                        fields[i].setPrimaryKeyIndex(num);
-                        pks[num] = fields[i];
-                        num++;
-                    }
-                }
-                _allPKFields = pks;
-            }
-        }
-        return _allPKFields;
-    }
-
-    /**
-     * Return the list of fields in the default fetch group,
-     * including superclass fields, or an empty array if none.
-     */
-    public FieldMetaData[] getDefaultFetchGroupFields() {
-        if (_allDFGFields == null) {
-            FieldMetaData[] fields = getFields();
-            int num = 0;
-            for (int i = 0; i < fields.length; i++)
-                if (fields[i].isInDefaultFetchGroup())
-                    num++;
-
-            FieldMetaData[] dfgs = _repos.newFieldMetaDataArray(num);
-            num = 0;
-            for (int i = 0; i < fields.length; i++)
-                if (fields[i].isInDefaultFetchGroup())
-                    dfgs[num++] = fields[i];
-            _allDFGFields = dfgs;
-        }
-        return _allDFGFields;
-    }
-
-    /**
-     * Return the version field for this class, if any.
-     */
-    public FieldMetaData getVersionField() {
-        if (_versionIdx == Integer.MIN_VALUE) {
-            FieldMetaData[] fields = getFields();
-            int idx = -1;
-            for (int i = 0; i < fields.length; i++) {
-                if (fields[i].isVersion()) {
-                    if (idx != -1)
-                        throw new MetaDataException(_loc.get
-                            ("mult-vers-fields", this, fields[idx], fields[i]));
-                    idx = i;
-                }
-            }
-            _versionIdx = idx;
-        }
-        if (_versionIdx == -1)
-            return null;
-        return getFields()[_versionIdx];
-    }
-
-    /**
-     * Return the metadata for the persistent or transactional field with
-     * the given absolute index.
-     *
-     * @return the field's metadata, or null if not found
-     */
-    public FieldMetaData getField(int index) {
-        FieldMetaData[] fields = getFields();
-        if (index < 0 || index >= fields.length)
-            return null;
-        return fields[index];
-    }
-
-    /**
-     * Return the metadata for the persistent or transactional field with
-     * the given relative index.
-     *
-     * @return the field's metadata, or null if not found
-     */
-    public FieldMetaData getDeclaredField(int index) {
-        FieldMetaData[] fields = getDeclaredFields();
-        if (index < 0 || index >= fields.length)
-            return null;
-        return fields[index];
-    }
-
-    /**
-     * Return the metadata for the persistent or transactional field with
-     * the given name.
-     *
-     * @return the field's metadata, or null if not found
-     */
-    public FieldMetaData getField(String name) {
-        FieldMetaData fmd = getDeclaredField(name);
-        if (fmd != null)
-            return fmd;
-        if (_supFieldMap != null && _defSupFields) {
-            fmd = (FieldMetaData) _supFieldMap.get(name);
-            if (fmd != null)
-                return fmd;
-        }
-        if (_super != null)
-            return getPCSuperclassMetaData().getField(name);
-        return null;
-    }
-
-    /**
-     * Return the metadata for the persistent or transactional field with
-     * the given name, without including superclass fields.
-     *
-     * @return the field's metadata, or null if not found
-     */
-    public FieldMetaData getDeclaredField(String name) {
-        FieldMetaData field = (FieldMetaData) _fieldMap.get(name);
-        if (field == null || field.getManagement() == field.MANAGE_NONE)
-            return null;
-        return field;
-    }
-
-    /**
-     * Return any fields that were added as non-managed.
-     * All other methods to get fields return only those that are managed.
-     */
-    public FieldMetaData[] getDeclaredUnmanagedFields() {
-        if (_unmgdFields == null) {
-            Collection unmanaged = new ArrayList(3);
-            FieldMetaData field;
-            for (Iterator itr = _fieldMap.values().iterator(); itr.hasNext();) {
-                field = (FieldMetaData) itr.next();
-                if (field.getManagement() == FieldMetaData.MANAGE_NONE)
-                    unmanaged.add(field);
-            }
-            _unmgdFields = (FieldMetaData[]) unmanaged.toArray
-                (_repos.newFieldMetaDataArray(unmanaged.size()));
-        }
-        return _unmgdFields;
-    }
-
-    /**
-     * Add a new field metadata to this class.
-     */
-    public FieldMetaData addDeclaredField(String name, Class type) {
-        FieldMetaData fmd = _repos.newFieldMetaData(name, type, this);
-        clearFieldCache();
-        _fieldMap.put(name, fmd);
-        return fmd;
-    }
-
-    /**
-     * Remove the given field from management.
-     *
-     * @return true if the field was removed, false otherwise
-     */
-    public boolean removeDeclaredField(FieldMetaData field) {
-        if (field != null && _fieldMap.remove(field.getName()) != null) {
-            clearFieldCache();
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Return the defined superclass field with the given name, or null if none.
-     */
-    public FieldMetaData getDefinedSuperclassField(String name) {
-        if (_supFieldMap == null)
-            return null;
-        return (FieldMetaData) _supFieldMap.get(name);
-    }
-
-    /**
-     * Add a new defined superclass field metadata to this class.
-     */
-    public FieldMetaData addDefinedSuperclassField(String name, Class type,
-        Class sup) {
-        FieldMetaData fmd = _repos.newFieldMetaData(name, type, this);
-        fmd.setDeclaringType(sup);
-        clearAllFieldCache();
-        _defSupFields = false;
-        if (_supFieldMap == null)
-            _supFieldMap = new HashMap();
-        _supFieldMap.put(name, fmd);
-        return fmd;
-    }
-
-    /**
-     * Remove the given field from management.
-     *
-     * @return true if the field was removed, false otherwise
-     */
-    public boolean removeDefinedSuperclassField(FieldMetaData field) {
-        if (field != null && _supFieldMap != null
-            && _supFieldMap.remove(field.getName()) != null) {
-            clearAllFieldCache();
-            _defSupFields = false;
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Incorporate superclass fields redefined in this subclass into this
-     * metadata. This method is generally called after metadata is resolved
-     * and mapping information is loaded, but before mapping resolve.
-     *
-     * @param force whether to force re-mapping of even mapped superclass fields
-     */
-    public void defineSuperclassFields(boolean force) {
-        if (_defSupFields)
-            return;
-
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (isMapped() && sup != null) {
-            // redefine all unmapped superclass fields
-            FieldMetaData[] sups = sup.getFields();
-            for (int i = 0; i < sups.length; i++) {
-                if ((force || !sups[i].getDefiningMetaData().isMapped())
-                    && getDefinedSuperclassField(sups[i].getName()) == null) {
-                    addDefinedSuperclassField(sups[i].getName(),
-                        sups[i].getDeclaredType(), sups[i].getDeclaringType());
-                }
-            }
-        }
-        resolveDefinedSuperclassFields();
-
-        // this ensures that all field indexes get set when fields are cached.
-        // I don't like doing this twice (it's also done in resolveMeta), but
-        // we have to re-cache in case this class or any superclass replaced
-        // some fields with redefined versions, and I don't want outside code
-        // to have to call this method after resolve just to get field indexes,
-        // etc set correctly
-        clearAllFieldCache();
-        cacheFields();
-    }
-
-    /**
-     * Resolve superclass fields we've redefined.
-     */
-    private void resolveDefinedSuperclassFields() {
-        _defSupFields = true;
-        if (_supFieldMap == null)
-            return;
-
-        FieldMetaData fmd;
-        FieldMetaData sup;
-        for (Iterator itr = _supFieldMap.values().iterator(); itr.hasNext();) {
-            fmd = (FieldMetaData) itr.next();
-            sup = getSuperclassField(fmd);
-
-            // jpa metadata doesn't qualify superclass field names, so we
-            // might not know the declaring type until now
-            if (fmd.getDeclaringType() == Object.class) {
-                fmd.setDeclaringType(sup.getDeclaringType());
-                fmd.backingMember(getRepository().getMetaDataFactory().
-                    getDefaults().getBackingMember(fmd));
-            }
-            fmd.copy(sup);
-            fmd.resolve(MODE_META);
-        }
-    }
-
-    /**
-     * Returns an array of all the fields defined by this class.
-     * This includes mapped declared fields and any concrete mapping of
-     * unmapped superclass fields performed by this class.
-     */
-    public FieldMetaData[] getDefinedFields() {
-        if (_definedFields == null) {
-            FieldMetaData[] fields = getFields();
-            List defined = new ArrayList(fields.length);
-            for (int i = 0; i < fields.length; i++) {
-                if (fields[i].isMapped()
-                    && fields[i].getDefiningMetaData() == this)
-                    defined.add(fields[i]);
-            }
-            _definedFields = (FieldMetaData[]) defined.toArray
-                (_repos.newFieldMetaDataArray(defined.size()));
-        }
-        return _definedFields;
-    }
-
-    /**
-     * Returns all fields in the order they are listed in the metadata
-     * file. Unlisted fields are placed after listed ones.
-     */
-    public FieldMetaData[] getFieldsInListingOrder() {
-        if (_allListingFields == null) {
-            // combine declared and unmanaged fields into listing order array
-            FieldMetaData[] dec = getDeclaredFields();
-            FieldMetaData[] unmgd = getDeclaredUnmanagedFields();
-            FieldMetaData[] decListing = _repos.newFieldMetaDataArray
-                (dec.length + unmgd.length);
-            System.arraycopy(dec, 0, decListing, 0, dec.length);
-            System.arraycopy(unmgd, 0, decListing, dec.length, unmgd.length);
-            Arrays.sort(decListing, ListingOrderComparator.getInstance());
-
-            if (_super == null)
-                _allListingFields = decListing;
-            else {
-                // place superclass fields in listing order before our
-                // listing-order declared fields
-                FieldMetaData[] sup = getPCSuperclassMetaData().
-                    getFieldsInListingOrder();
-                FieldMetaData[] listing = _repos.newFieldMetaDataArray
-                    (sup.length + decListing.length);
-                System.arraycopy(sup, 0, listing, 0, sup.length);
-                replaceDefinedSuperclassFields(listing, sup.length);
-                System.arraycopy(decListing, 0, listing, sup.length,
-                    decListing.length);
-                _allListingFields = listing;
-            }
-        }
-        return _allListingFields;
-    }
-
-    /**
-     * Returns all fields defined by this class in the order they are listed
-     * in the metadata file. Unlisted fields are placed after listed ones.
-     * This array includes declared transactional and unmanaged fields.
-     */
-    public FieldMetaData[] getDefinedFieldsInListingOrder() {
-        if (_listingFields == null) {
-            FieldMetaData[] fields = getFields();
-            List defined = new ArrayList(fields.length);
-            for (int i = 0; i < fields.length; i++)
-                if (fields[i].getDefiningMetaData() == this)
-                    defined.add(fields[i]);
-            FieldMetaData[] unmgd = getDeclaredUnmanagedFields();
-            FieldMetaData[] listing = _repos.newFieldMetaDataArray
-                (defined.size() + unmgd.length);
-            for (int i = 0; i < defined.size(); i++)
-                listing[i] = (FieldMetaData) defined.get(i);
-            System.arraycopy(unmgd, 0, listing, defined.size(), unmgd.length);
-            Arrays.sort(listing, ListingOrderComparator.getInstance());
-            _listingFields = listing;
-        }
-        return _listingFields;
-    }
-
-    /**
-     * The name of the datacache to use for this class, or null if none.
-     */
-    public String getDataCacheName() {
-        if (DEFAULT_STRING.equals(_cacheName)) {
-            if (_super != null)
-                _cacheName = getPCSuperclassMetaData().getDataCacheName();
-            else
-                _cacheName = DataCache.NAME_DEFAULT;
-        }
-        return _cacheName;
-    }
-
-    /**
-     * Set the cache name for this class. Set to null to disable caching.
-     */
-    public void setDataCacheName(String name) {
-        _cacheName = name;
-    }
-
-    /**
-     * The cache timeout for this class. -1 indicates no timeout.
-     */
-    public int getDataCacheTimeout() {
-        if (_cacheTimeout == Integer.MIN_VALUE) {
-            if (_super != null)
-                _cacheTimeout = getPCSuperclassMetaData().
-                    getDataCacheTimeout();
-            else
-                _cacheTimeout = _repos.getConfiguration().
-                    getDataCacheTimeout();
-        }
-        return _cacheTimeout;
-    }
-
-    /**
-     * The cache timeout for this class. -1 indicates no timeout.
-     */
-    public void setDataCacheTimeout(int timeout) {
-        _cacheTimeout = timeout;
-    }
-
-    /**
-     * Return the data cache for this class, or null if it is not cachable.
-     */
-    public DataCache getDataCache() {
-        String name = getDataCacheName();
-        if (name == null)
-            return null;
-        return _repos.getConfiguration().getDataCacheManagerInstance().
-            getDataCache(name, true);
-    }
-
-    /**
-     * Whether instances are detachable.
-     */
-    public boolean isDetachable() {
-        if (_detachable == null) {
-            if (_super != null)
-                _detachable = (getPCSuperclassMetaData().isDetachable())
-                    ? Boolean.TRUE : Boolean.FALSE;
-            else
-                _detachable = Boolean.FALSE;
-        }
-        return _detachable.booleanValue();
-    }
-
-    /**
-     * Whether instances are detachable.
-     */
-    public void setDetachable(boolean detachable) {
-        _detachable = (detachable) ? Boolean.TRUE : Boolean.FALSE;
-    }
-
-    /**
-     * The name of the detach state field, or null if none.
-     */
-    public String getDetachedState() {
-        if (DEFAULT_STRING.equals(_detachState)) {
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null && sup.isDetachable() == isDetachable())
-                _detachState = sup.getDetachedState();
-            else {
-                Boolean use = usesDetachedState(SYNTHETIC, true);
-                _detachState = (Boolean.FALSE.equals(use)) ? null : SYNTHETIC;
-            }
-        }
-        return _detachState;
-    }
-
-    /**
-     * The name of the detach state field, or null if none.
-     */
-    public void setDetachedState(String field) {
-        _detachState = field;
-    }
-
-    /**
-     * Return the detach state field, or null if none.
-     */
-    public Field getDetachedStateField() {
-        // no caching; only used at enhancement
-        String fieldName = getDetachedState();
-        if (fieldName == null || SYNTHETIC.equals(fieldName))
-            return null;
-
-        Field f = Reflection.findField(_type, fieldName, false);
-        if (f != null)
-            return f;
-        else
-            throw new MetaDataException(
-                _loc.get("no-detach-state", fieldName, _type));
-    }
-
-    /**
-     * Whether an instance of this type has detached state.
-     *
-     * @return true if a detached instance must have detached state, false
-     * if it does not, and null if it may use a
-     * manually-constructed instance without detached state
-     */
-    public Boolean usesDetachedState() {
-        // no need to let conf disallow because it's taken into account in
-        // getDetachedState() call
-        return usesDetachedState(getDetachedState(), false);
-    }
-
-    /**
-     * Whether an instance of this type has detached state, assuming the given
-     * detached state field.
-     *
-     * @return true if a detached instance must have detached state, false
-     * if it does not, and null if it may use a
-     * manually-constructed instance without detached state
-     */
-    private Boolean usesDetachedState(String detachedField,
-        boolean confDisallows) {
-        if (!isDetachable())
-            return Boolean.FALSE;
-
-        // if we declare a detached state field, have to use it
-        if (detachedField == null)
-            return Boolean.FALSE;
-        if (!SYNTHETIC.equals(detachedField))
-            return Boolean.TRUE;
-
-        // allow conf to disallow
-        if (confDisallows && !_repos.getConfiguration().
-            getDetachStateInstance().getDetachedStateField())
-            return Boolean.FALSE;
-
-        // have to use detached state to store datastore id
-        if (getIdentityType() == ID_DATASTORE)
-            return Boolean.TRUE;
-
-        // allow detached state use, but don't require
-        return null;
-    }
-
-    /**
-     * Clear cached field data.
-     */
-    protected void clearAllFieldCache() {
-        _allFields = null;
-        _allDFGFields = null;
-        _allPKFields = null;
-        _definedFields = null;
-        _listingFields = null;
-        _allListingFields = null;
-        _fieldDataTable = null;
-    }
-
-    /**
-     * Clear defined field data.
-     */
-    protected void clearDefinedFieldCache() {
-        _definedFields = null;
-        _listingFields = null;
-    }
-
-    /**
-     * Clear cached field data.
-     */
-    protected void clearFieldCache() {
-        clearAllFieldCache();
-        _fields = null;
-        _unmgdFields = null;
-        _versionIdx = Integer.MIN_VALUE;
-    }
-
-    /**
-     * Clear cached subclass data.
-     */
-    protected void clearSubclassCache() {
-        _subs = null;
-        _subMetas = null;
-        _mapSubMetas = null;
-    }
-
-    /**
-     * Clear impl data and intermediate data table.
-     */
-    void clearExtraFieldDataTable() {
-        _fieldDataTable = null;
-    }
-
-    /**
-     * Cache field arrays.
-     */
-    private void cacheFields() {
-        getFields();
-        getPrimaryKeyFields();
-    }
-
-    public int hashCode() {
-        return _type.getName().hashCode();
-    }
-
-    public boolean equals(Object other) {
-        if (other == this)
-            return true;
-        if (!(other instanceof ClassMetaData))
-            return false;
-        return _type == ((ClassMetaData) other).getDescribedType();
-    }
-
-    public int compareTo(Object other) {
-        if (other == this)
-            return 0;
-        return _type.getName().compareTo(((ClassMetaData) other).
-            getDescribedType().getName());
-    }
-
-    public String toString() {
-        return getDescribedType().getName();
-    }
-
-    ////////////////////////
-    // Resolve and validate
-    ////////////////////////
-
-    /**
-     * The resolve mode for this metadata.
-     */
-    public int getResolve() {
-        return _resMode;
-    }
-
-    /**
-     * The resolve mode for this metadata.
-     */
-    public void setResolve(int mode) {
-        _resMode = mode;
-    }
-
-    /**
-     * The resolve mode for this metadata.
-     */
-    public void setResolve(int mode, boolean on) {
-        if (mode == MODE_NONE)
-            _resMode = mode;
-        else if (on)
-            _resMode |= mode;
-        else
-            _resMode &= ~mode;
-    }
-
-    /**
-     * Resolve and validate metadata. Return true if already resolved.
-     */
-    public boolean resolve(int mode) {
-        if ((_resMode & mode) == mode)
-            return true;
-        int cur = _resMode;
-        _resMode |= mode;
-
-        int val = _repos.getValidate();
-        boolean runtime = (val & _repos.VALIDATE_RUNTIME) != 0;
-        boolean validate =
-            !ImplHelper.isManagedType(getRepository().getConfiguration(), _type)
-            || (val & MetaDataRepository.VALIDATE_UNENHANCED) == 0;
-
-        // we only do any actions for metadata mode
-        if ((mode & MODE_META) != 0 && (cur & MODE_META) == 0) {
-            resolveMeta(runtime);
-            if (validate && (val & _repos.VALIDATE_META) != 0)
-                validateMeta(runtime);
-        }
-        if ((mode & MODE_MAPPING) != 0 && (cur & MODE_MAPPING) == 0) {
-            resolveMapping(runtime);
-            if (validate && (val & _repos.VALIDATE_MAPPING) != 0)
-                validateMapping(runtime);
-        }
-        if ((mode & MODE_MAPPING_INIT) != 0 && (cur & MODE_MAPPING_INIT) == 0)
-            initializeMapping();
-        return false;
-    }
-
-    /**
-     * Resolve metadata.
-     */
-    protected void resolveMeta(boolean runtime) {
-        boolean embed = _owner != null && _owner.getDeclaredType() == _type;
-        Log log = _repos.getLog();
-        if (log.isTraceEnabled())
-            log.trace(_loc.get((embed) ? "resolve-embed-meta" : "resolve-meta",
-                this + "@" + System.identityHashCode(this)));
-
-        if (runtime && !_type.isInterface() &&
-            !ImplHelper.isManagedType(getRepository().getConfiguration(),_type))
-            throw new MetaDataException(_loc.get("not-enhanced", _type));
-
-        // are we the target of an embedded value?
-        if (embed) {
-            if (_owner.getFieldMetaData().getDefiningMetaData().
-                getDescribedType().isAssignableFrom(_type))
-                throw new MetaDataException(_loc.get("recurse-embed", _owner));
-
-            // copy info from the "real" metadata for this type
-            ClassMetaData meta = _repos.getMetaData(_type, _loader, true);
-            meta.resolve(MODE_META);
-            copy(this, meta);
-            _embedded = Boolean.FALSE; // embedded instance isn't embedded-only
-        }
-
-        // make sure superclass is resolved
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup != null) {
-            sup.resolve(MODE_META);
-            if (embed) {
-                // embedded instance always redefine all superclass fields
-                FieldMetaData[] sups = sup.getFields();
-                for (int i = 0; i < sups.length; i++) {
-                    if (_supFieldMap == null
-                        || !_supFieldMap.containsKey(sups[i].getName())) {
-                        addDefinedSuperclassField(sups[i].getName(),
-                            sups[i].getDeclaredType(),
-                            sups[i].getDeclaringType());
-                    }
-                }
-            }
-        }
-
-        // resolve fields and remove invalids
-        FieldMetaData fmd;
-        for (Iterator itr = _fieldMap.values().iterator(); itr.hasNext();) {
-            // only pass on metadata resolve mode so that metadata is always
-            // resolved before any other resolve modes our subclasses pass along
-            fmd = (FieldMetaData) itr.next();
-            fmd.resolve(MODE_META);
-
-            if (!fmd.isExplicit()
-                && (fmd.getDeclaredTypeCode() == JavaTypes.OBJECT
-                || fmd.getDeclaredTypeCode() == JavaTypes.PC_UNTYPED
-                || (fmd.getDeclaredTypeCode() == JavaTypes.ARRAY
-                && fmd.getElement().getDeclaredTypeCode()
-                == JavaTypes.OBJECT))) {
-                _repos.getLog().warn(_loc.get("rm-field", fmd));
-                if (fmd.getListingIndex() != -1)
-                    fmd.setManagement(fmd.MANAGE_NONE);
-                else
-                    itr.remove();
-                clearFieldCache();
-            }
-        }
-
-        // embedded instances must embed all superclass fields too
-        if (embed) {
-            clearAllFieldCache();
-            resolveDefinedSuperclassFields();
-        }
-
-        // this ensures that all field indexes get set when fields are cached
-        cacheFields();
-
-        // resolve lifecycle metadata now to prevent lazy threading problems
-        _lifeMeta.resolve();
-
-        // record implements in the repository
-        if (_interfaces != null) {
-            for (Iterator it = _interfaces.iterator(); it.hasNext();)
-                _repos.addDeclaredInterfaceImpl(this, (Class) it.next());
-        }
-
-        // resolve fetch groups
-        if (_fgMap != null)
-            for (Iterator itr = _fgMap.values().iterator(); itr.hasNext();)
-                ((FetchGroup) itr.next()).resolve();
-
-        if (!embed && _type.isInterface()) {
-            if (_interface != Boolean.TRUE)
-                throw new MetaDataException(_loc.get("interface", _type));
-
-            if (runtime) {
-                _impl = _repos.getImplGenerator().createImpl(this);
-                _repos.setInterfaceImpl(this, _impl);
-            }
-        }
-
-        // if this is runtime, create a pc instance and scan it for comparators
-        if (runtime && !Modifier.isAbstract(_type.getModifiers())) {
-            ProxySetupStateManager sm = new ProxySetupStateManager();
-            sm.setProxyData(PCRegistry.newInstance(_type, sm, false), this);
-        }
-    }
-
-    /**
-     * Validate resolved metadata.
-     */
-    protected void validateMeta(boolean runtime) {
-        validateDataCache();
-        validateDetachable();
-        validateExtensionKeys();
-        validateIdentity();
-        validateAccessType();
-    }
-
-    /**
-     * Resolve mapping data. Logs resolve message and resolves super by default.
-     */
-    protected void resolveMapping(boolean runtime) {
-        Log log = _repos.getLog();
-        if (log.isTraceEnabled())
-            log.trace(_loc.get("resolve-mapping", this + "@"
-                + System.identityHashCode(this)));
-
-        // make sure superclass is resolved first
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup != null)
-            sup.resolve(MODE_MAPPING);
-    }
-
-    /**
-     * Validate mapping data.
-     */
-    protected void validateMapping(boolean runtime) {
-    }
-
-    /**
-     * Initialize mapping. Logs init message by default.
-     */
-    protected void initializeMapping() {
-        Log log = _repos.getLog();
-        if (log.isTraceEnabled())
-            log.trace(_loc.get("init-mapping", this + "@"
-                + System.identityHashCode(this)));
-    }
-
-    /**
-     * Validate data cache settings.
-     */
-    private void validateDataCache() {
-        int timeout = getDataCacheTimeout();
-        if (timeout < -1 || timeout == 0)
-            throw new MetaDataException(_loc.get("cache-timeout-invalid",
-                _type, String.valueOf(timeout)));
-
-        if (_super == null)
-            return;
-        String cache = getDataCacheName();
-        if (cache == null)
-            return;
-
-        String superCache = getPCSuperclassMetaData().getDataCacheName();
-        if (!StringUtils.equals(cache, superCache))
-            throw new MetaDataException(_loc.get("cache-names", new Object[]
-                { _type, cache, _super, superCache }));
-    }
-
-    /**
-     * Assert that the identity handling for this class is valid.
-     */
-    private void validateIdentity() {
-        // make sure identity types are consistent
-        ClassMetaData sup = getPCSuperclassMetaData();
-        int id = getIdentityType();
-        if (sup != null && sup.getIdentityType() != ID_UNKNOWN
-            && sup.getIdentityType() != id)
-            throw new MetaDataException(_loc.get("id-types", _type));
-
-        // check for things the data store doesn't support
-        Collection opts = _repos.getConfiguration().supportedOptions();
-        if (id == ID_APPLICATION
-            && !opts.contains(OpenJPAConfiguration.OPTION_ID_APPLICATION)) {
-            throw new UnsupportedException(_loc.get("appid-not-supported",
-                _type));
-        }
-        if (id == ID_DATASTORE
-            && !opts.contains(OpenJPAConfiguration.OPTION_ID_DATASTORE)) {
-            throw new UnsupportedException(_loc.get
-                ("datastoreid-not-supported", _type));
-        }
-
-        if (id == ID_APPLICATION) {
-            if (_idStrategy != ValueStrategies.NONE)
-                throw new MetaDataException(_loc.get("appid-strategy", _type));
-            validateAppIdClass();
-        } else if (id != ID_UNKNOWN)
-            validateNoPKFields();
-
-        int strategy = getIdentityStrategy();
-        if (strategy == ValueStrategies.SEQUENCE
-            && getIdentitySequenceName() == null)
-            throw new MetaDataException(_loc.get("no-seq-name", _type));
-
-        ValueStrategies.assertSupported(strategy, this,
-            "datastore identity strategy");
-    }
-
-    /**
-     * Make sure the application identity class is valid.
-     */
-    private void validateAppIdClass() {
-        // base types must declare an oid class if not single-field identity
-        FieldMetaData[] pks = getPrimaryKeyFields();
-        if (getObjectIdType() == null) {
-            if (pks.length == 1)
-                throw new MetaDataException(_loc.get("unsupported-id-type",
-                    _type, pks[0].getName(),
-                    pks[0].getDeclaredType().getName()));
-            throw new MetaDataException(_loc.get("no-id-class", _type));
-        }
-        if (_objectId == null)
-            return;
-
-        if (isOpenJPAIdentity()) {
-            if (pks[0].getDeclaredTypeCode() == JavaTypes.OID) {
-                ClassMetaData embed = pks[0].getEmbeddedMetaData();
-                validateAppIdClassMethods(embed.getDescribedType());
-                validateAppIdClassPKs(embed, embed.getFields(),
-                    embed.getDescribedType());
-            }
-            return;
-        }
-
-        if (_super != null) {
-            // concrete superclass oids must match or be parent of ours
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (!sup.getObjectIdType().isAssignableFrom(_objectId))
-                throw new MetaDataException(_loc.get("id-classes",
-                    new Object[]{ _type, _objectId, _super,
-                        sup.getObjectIdType() }));
-
-            // validate that no other pks are declared if we have a
-            // concrete PC superclass
-            if (hasConcretePCSuperclass())
-                validateNoPKFields();
-        }
-
-        // if this class has its own oid class, do some more validation
-        if (_super == null
-            || _objectId != getPCSuperclassMetaData().getObjectIdType()) {
-            // make sure non-abstract oid classes override the proper methods
-            if (!Modifier.isAbstract(_objectId.getModifiers()))
-                validateAppIdClassMethods(_objectId);
-
-            // make sure the app id class has all pk fields
-            validateAppIdClassPKs(this, pks, _objectId);
-        }
-    }
-
-    /**
-     * Return true if this class has a concrete persistent superclass.
-     */
-    private boolean hasConcretePCSuperclass() {
-        if (_super == null)
-            return false;
-        if (!Modifier.isAbstract(_super.getModifiers()))
-            return true;
-        return getPCSuperclassMetaData().hasConcretePCSuperclass();
-    }
-
-    /**
-     * Ensure that the user has overridden the equals and hashCode methods,
-     * and has the proper constructors.
-     */
-    private void validateAppIdClassMethods(Class oid) {
-        try {
-            oid.getConstructor((Class[]) null);
-        } catch (Exception e) {
-            throw new MetaDataException(_loc.get("null-cons", _type)).
-                setCause(e);
-        }
-
-        // check for equals and hashcode overrides; don't enforce it
-        // for abstract app id classes, since they may not necessarily
-        // declare primary key fields
-        Method method;
-        try {
-            method = oid.getMethod("equals", new Class[]{ Object.class });
-        } catch (Exception e) {
-            throw new GeneralException(e).setFatal(true);
-        }
-
-        boolean abs = Modifier.isAbstract(_type.getModifiers());
-        if (!abs && method.getDeclaringClass() == Object.class)
-            throw new MetaDataException(_loc.get("eq-method", _type));
-
-        try {
-            method = oid.getMethod("hashCode", (Class[]) null);
-        } catch (Exception e) {
-            throw new GeneralException(e).setFatal(true);
-        }
-        if (!abs && method.getDeclaringClass() == Object.class)
-            throw new MetaDataException(_loc.get("hc-method", _type));
-    }
-
-    /**
-     * Validate that the primary key class has all pk fields.
-     */
-    private void validateAppIdClassPKs(ClassMetaData meta,
-        FieldMetaData[] fmds, Class oid) {
-        if (fmds.length == 0 && !Modifier.isAbstract(meta.getDescribedType().
-            getModifiers()))
-            throw new MetaDataException(_loc.get("no-pk", _type));
-
-        // check that the oid type contains all pk fields
-        Field f;
-        Method m;
-        Class c;
-        for (int i = 0; i < fmds.length; i++) {
-            switch (fmds[i].getDeclaredTypeCode()) {
-                case JavaTypes.ARRAY:
-                    c = fmds[i].getDeclaredType().getComponentType();
-                    if (c == byte.class || c == Byte.class
-                        || c == char.class || c == Character.class) {
-                        c = fmds[i].getDeclaredType();
-                        break;
-                    }
-                    // else no break
-                case JavaTypes.PC_UNTYPED:
-                case JavaTypes.COLLECTION:
-                case JavaTypes.MAP:
-                case JavaTypes.OID: // we're validating embedded fields
-                    throw new MetaDataException(_loc.get("bad-pk-type",
-                        fmds[i]));
-                default:
-                    c = fmds[i].getObjectIdFieldType();
-            }
-
-            if (meta.getAccessType() == ACCESS_FIELD) {
-                f = Reflection.findField(oid, fmds[i].getName(), false);
-                if (f == null || !f.getType().isAssignableFrom(c))
-                    throw new MetaDataException(_loc.get("invalid-id",
-                        _type, fmds[i].getName()));
-            } else if (meta.getAccessType() == ACCESS_PROPERTY) {
-                m = Reflection.findGetter(oid, fmds[i].getName(), false);
-                if (m == null || !m.getReturnType().isAssignableFrom(c))
-                    throw new MetaDataException(_loc.get("invalid-id",
-                        _type, fmds[i].getName()));
-                m = Reflection.findSetter(oid, fmds[i].getName(),
-                    fmds[i].getObjectIdFieldType(), false);
-                if (m == null || m.getReturnType() != void.class)
-                    throw new MetaDataException(_loc.get("invalid-id",
-                        _type, fmds[i].getName()));
-            }
-        }
-    }
-
-    /**
-     * Validate that this class doesn't declare any primary key fields.
-     */
-    private void validateNoPKFields() {
-        FieldMetaData[] fields = getDeclaredFields();
-        for (int i = 0; i < fields.length; i++)
-            if (fields[i].isPrimaryKey())
-                throw new MetaDataException(_loc.get("bad-pk", fields[i]));
-    }
-
-    /**
-     * Assert that this class' access type is allowed.
-     */
-    private void validateAccessType() {
-        if (_accessType == ACCESS_UNKNOWN)
-            return;
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup != null && sup.getAccessType() != ACCESS_UNKNOWN
-            && sup.getAccessType() != _accessType &&
-            getPCSuperclassMetaData().getFields().length > 0) {
-            throw new MetaDataException(_loc.get("inconsistent-access",
-                this, sup));
-        }
-    }
-
-    /**
-     * Assert that detachment configuration is valid.
-     */
-    private void validateDetachable() {
-        boolean first = true;
-        for (ClassMetaData parent = getPCSuperclassMetaData();
-            first && parent != null; parent = parent.getPCSuperclassMetaData())
-        {
-            if (parent.isDetachable())
-                first = false;
-        }
-
-        Field field = getDetachedStateField();
-        if (field != null) {
-            if (!first)
-                throw new MetaDataException(_loc.get("parent-detach-state",
-                    _type));
-            if (getField(field.getName()) != null)
-                throw new MetaDataException(_loc.get("managed-detach-state",
-                    field.getName(), _type));
-            if (field.getType() != Object.class)
-                throw new MetaDataException(_loc.get("bad-detach-state",
-                    field.getName(), _type));
-        }
-    }
-
-    ///////////////
-    // Fetch Group
-    ///////////////
-
-    /**
-     * Return the fetch groups declared explicitly in this type.
-     */
-    public FetchGroup[] getDeclaredFetchGroups() {
-        if (_fgs == null)
-            _fgs = (_fgMap == null) ? EMPTY_FETCH_GROUP_ARRAY : (FetchGroup[])
-                _fgMap.values().toArray(new FetchGroup[_fgMap.size()]); 
-        return _fgs;
-    }
-
-    /**
-     * Return all fetch groups for this type, including superclass groups.
-     */
-    public FetchGroup[] getCustomFetchGroups() {
-        if (_customFGs == null) {
-            // map fgs to names, allowing our fgs to override supers
-            Map fgs = new HashMap();
-            ClassMetaData sup = getPCSuperclassMetaData();
-            if (sup != null)
-            {
-                FetchGroup[] supFGs = sup.getCustomFetchGroups();
-                for (int i = 0; i < supFGs.length; i++)
-                    fgs.put(supFGs[i].getName(), supFGs[i]);
-            }
-            FetchGroup[] decs = getDeclaredFetchGroups();
-            for (int i = 0; i < decs.length; i++)
-                fgs.put(decs[i].getName(), decs[i]);
-            
-            // remove std groups
-            fgs.remove(FetchGroup.NAME_DEFAULT);
-            fgs.remove(FetchGroup.NAME_ALL);
-
-            _customFGs = (FetchGroup[]) fgs.values().toArray
-                (new FetchGroup[fgs.size()]);
-        }
-        return _customFGs;
-    }
-
-    /**
-     * Gets a named fecth group. If not available in this receiver then looks
-     * up the inheritence hierarchy. 
-     *
-     * @param name name of a fetch group.
-     * @return an existing fecth group of the given name if known to this 
-     * receiver or any of its superclasses. Otherwise null.
-     */
-    public FetchGroup getFetchGroup(String name) {
-        FetchGroup fg = (_fgMap == null) ? null : (FetchGroup) _fgMap.get(name);
-        if (fg != null)
-            return fg;
-        ClassMetaData sup = getPCSuperclassMetaData();
-        if (sup != null)
-            return sup.getFetchGroup(name);
-        if (FetchGroup.NAME_DEFAULT.equals(name))
-            return FetchGroup.DEFAULT;
-        if (FetchGroup.NAME_ALL.equals(name))
-            return FetchGroup.ALL;
-        return null;
-    }
-
-    /**
-     * Adds fetch group of the given name, or returns existing instance.
-     *
-     * @param name a non-null, non-empty name. Must be unique within this
-     * receiver's scope. The super class <em>may</em> have a group with
-     * the same name.
-     */
-    public FetchGroup addDeclaredFetchGroup(String name) {
-    	if (StringUtils.isEmpty(name))
-    		throw new MetaDataException(_loc.get("empty-fg-name", this));
-        if (_fgMap == null)
-            _fgMap = new HashMap();
-        FetchGroup fg = (FetchGroup) _fgMap.get(name);
-        if (fg == null) {
-        	fg = new FetchGroup(this, name);
-        	_fgMap.put(name, fg);
-            _fgs = null;
-            _customFGs = null;
-        }
-        return fg;
-    }
-
-    /**
-     * Remove a declared fetch group.
-     */
-    public boolean removeDeclaredFetchGroup(FetchGroup fg) {
-        if (fg == null)
-            return false;
-        if (_fgMap.remove(fg.getName()) != null) {
-            _fgs = null;
-            _customFGs = null;
-            return true;
-        }
-        return false;
-    }
-
-    /////////////////
-    // SourceTracker
-    /////////////////
-
-    public File getSourceFile() {
-        return _srcFile;
-    }
-
-    public Object getSourceScope() {
-        return null;
-    }
-
-    public int getSourceType() {
-        return _srcType;
-    }
-
-    public void setSource(File file, int srcType) {
-        _srcFile = file;
-        _srcType = srcType;
-    }
-
-    public String getResourceName() {
-        return _type.getName();
-    }
-
-    /**
-     * The source mode this metadata has been loaded under.
-     */
-    public int getSourceMode() {
-        return _srcMode;
-    }
-
-    /**
-     * The source mode this metadata has been loaded under.
-     */
-    public void setSourceMode(int mode) {
-        _srcMode = mode;
-    }
-
-    /**
-     * The source mode this metadata has been loaded under.
-     */
-    public void setSourceMode(int mode, boolean on) {
-        if (mode == MODE_NONE)
-            _srcMode = mode;
-        else if (on)
-            _srcMode |= mode;
-        else
-            _srcMode &= ~mode;
-    }
-
-    /**
-     * The index in which this class was listed in the metadata. Defaults to
-     * <code>-1</code> if this class was not listed in the metadata.
-     */
-    public int getListingIndex() {
-        return _listIndex;
-    }
-
-    /**
-     * The index in which this field was listed in the metadata. Defaults to
-     * <code>-1</code> if this class was not listed in the metadata.
-     */
-    public void setListingIndex(int index) {
-        _listIndex = index;
-    }
-
-    ///////////////
-    // Commentable
-    ///////////////
-
-    public String[] getComments() {
-        return (_comments == null) ? EMPTY_COMMENTS : _comments;
-    }
-
-    public void setComments(String[] comments) {
-        _comments = comments;
-    }
-
-    //////////////
-    // State copy
-    //////////////
-
-    /**
-     * Copy the metadata from the given instance to this one. Do not
-     * copy mapping information.
-     */
-    public void copy(ClassMetaData meta) {
-        if (meta.getDescribedType() != _type)
-            throw new InternalException();
-        super.copy(meta);
-
-        // copy class-level info; use get methods to force resolution of
-        // lazy data
-        _super = meta.getPCSuperclass();
-        _objectId = meta.getObjectIdType();
-        _extent = (meta.getRequiresExtent()) ? Boolean.TRUE : Boolean.FALSE;
-        _embedded = (meta.isEmbeddedOnly()) ? Boolean.TRUE : Boolean.FALSE;
-        _interface = (meta.isManagedInterface()) ? Boolean.TRUE : Boolean.FALSE;
-        setIntercepting(meta.isIntercepting());
-        _impl = meta.getInterfaceImpl();
-        _identity = meta.getIdentityType();
-        _idStrategy = meta.getIdentityStrategy();
-        _seqName = meta.getIdentitySequenceName();
-        _seqMeta = null;
-        _alias = meta.getTypeAlias();
-        _accessType = meta.getAccessType();
-
-        // only copy this information if it wasn't set explicitly for this
-        // instance
-        if (DEFAULT_STRING.equals(_cacheName))
-            _cacheName = meta.getDataCacheName();
-        if (_cacheTimeout == Integer.MIN_VALUE)
-            _cacheTimeout = meta.getDataCacheTimeout();
-        if (_detachable == null)
-            _detachable = meta._detachable;
-        if (DEFAULT_STRING.equals(_detachState))
-            _detachState = meta.getDetachedState();
-
-        // synch field information; first remove extra fields
-        clearFieldCache();
-        _fieldMap.keySet().retainAll(meta._fieldMap.keySet());
-
-        // add copies of declared fields; other defined fields already copied
-        FieldMetaData[] fields = meta.getDeclaredFields();
-        FieldMetaData field;
-        for (int i = 0; i < fields.length; i++) {
-            field = getDeclaredField(fields[i].getName());
-            if (field == null)
-                field = addDeclaredField(fields[i].getName(),
-                    fields[i].getDeclaredType());
-            field.setDeclaredIndex(-1);
-            field.setIndex(-1);
-            field.copy(fields[i]);
-        }
-
-        // copy fetch groups
-        FetchGroup[] fgs = meta.getDeclaredFetchGroups();
-        FetchGroup fg;
-        for (int i = 0; i < fgs.length; i++) {
-            fg = addDeclaredFetchGroup(fgs[i].getName());
-            fg.copy(fgs[i]); 
-        }
-
-        // copy iface re-mapping
-        _ifaceMap.clear();
-        _ifaceMap.putAll(meta._ifaceMap);
-    }
-
-    /**
-     * Recursive helper to copy embedded metadata.
-     */
-    private static void copy(ClassMetaData embed, ClassMetaData dec) {
-        ClassMetaData sup = dec.getPCSuperclassMetaData();
-        if (sup != null) {
-            embed.setPCSuperclass(sup.getDescribedType());
-            copy(embed.getPCSuperclassMetaData(), sup);
-        }
-        embed.copy(dec);
-    }
-
-    protected void addExtensionKeys(Collection exts) {
-        _repos.getMetaDataFactory().addClassExtensionKeys(exts);
-    }
-
-    /**
-     * Comparator used to put field metadatas into listing order.
-     */
-    private static class ListingOrderComparator
-        implements Comparator {
-
-        private static final ListingOrderComparator _instance
-            = new ListingOrderComparator();
-
-        /**
-         * Access singleton instance.
-         */
-        public static ListingOrderComparator getInstance() {
-            return _instance;
-        }
-
-        public int compare(Object o1, Object o2) {
-            if (o1 == o2)
-                return 0;
-            if (o1 == null)
-                return 1;
-            if (o2 == null)
-                return -1;
-
-            FieldMetaData f1 = (FieldMetaData) o1;
-            FieldMetaData f2 = (FieldMetaData) o2;
-            if (f1.getListingIndex() == f2.getListingIndex()) {
-                if (f1.getIndex() == f2.getIndex())
-                    return f1.getFullName(false).compareTo
-                        (f2.getFullName(false));
-				if (f1.getIndex () == -1)
-					return 1;
-				if (f2.getIndex () == -1)
-					return -1;
-				return f1.getIndex () - f2.getIndex ();
-			}	
-			if (f1.getListingIndex () == -1)
-				return 1;
-			if (f2.getListingIndex () == -1)
-				return -1;
-			return f1.getListingIndex () - f2.getListingIndex ();
-		}
-	}
-}
+/*
+ * 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.openjpa.meta;
+
+import java.io.File;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.datacache.DataCache;
+import org.apache.openjpa.enhance.PCRegistry;
+import org.apache.openjpa.enhance.Reflection;
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.meta.SourceTracker;
+import org.apache.openjpa.lib.util.J2DoPrivHelper;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.lib.xml.Commentable;
+import org.apache.openjpa.util.BigDecimalId;
+import org.apache.openjpa.util.BigIntegerId;
+import org.apache.openjpa.util.ByteId;
+import org.apache.openjpa.util.CharId;
+import org.apache.openjpa.util.DateId;
+import org.apache.openjpa.util.DoubleId;
+import org.apache.openjpa.util.FloatId;
+import org.apache.openjpa.util.GeneralException;
+import org.apache.openjpa.util.IntId;
+import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.LongId;
+import org.apache.openjpa.util.MetaDataException;
+import org.apache.openjpa.util.ObjectId;
+import org.apache.openjpa.util.OpenJPAId;
+import org.apache.openjpa.util.ShortId;
+import org.apache.openjpa.util.StringId;
+import org.apache.openjpa.util.UnsupportedException;
+import org.apache.openjpa.util.ImplHelper;
+import serp.util.Strings;
+
+/**
+ * Contains metadata about a persistent type.
+ * This metadata is available both at enhancement time and runtime.
+ *  Note that this class employs aggressive caching, and therefore it is
+ * important to finalize the configuration of field metadatas before invoking
+ * methods that depend on that configuration, such as
+ * {@link #getPrimaryKeyFields}.
+ *
+ * @author Abe White
+ */
+public class ClassMetaData
+    extends Extensions
+    implements Comparable, SourceTracker, MetaDataContext, MetaDataModes,
+    Commentable {
+
+    /**
+     * Unkonwn identity type.
+     */
+    public static final int ID_UNKNOWN = 0;
+
+    /**
+     * Datastore identity type.
+     */
+    public static final int ID_DATASTORE = 1;
+
+    /**
+     * Application identity type.
+     */
+    public static final int ID_APPLICATION = 2;
+
+    /**
+     * Unknown access type.
+     */
+    public static final int ACCESS_UNKNOWN = 0;
+
+    /**
+     * Persistent attributes are accessed via direct field access. Bit flag.
+     */
+    public static final int ACCESS_FIELD = 2 << 0;
+
+    /**
+     * Persistent attributes are accessed via setters and getters. Bit flag.
+     */
+    public static final int ACCESS_PROPERTY = 2 << 1;
+
+    /**
+     * Value for using a synthetic detached state field, which is the default.
+     */
+    public static final String SYNTHETIC = "`syn";
+
+    protected static final String DEFAULT_STRING = "`";
+
+    private static final Localizer _loc = Localizer.forPackage
+        (ClassMetaData.class);
+
+    private static final FetchGroup[] EMPTY_FETCH_GROUP_ARRAY
+        = new FetchGroup[0];
+    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    private MetaDataRepository _repos;
+    private transient ClassLoader _loader = null;
+
+    private final ValueMetaData _owner;
+    private final LifecycleMetaData _lifeMeta = new LifecycleMetaData(this);
+    private File _srcFile = null;
+    private int _srcType = SRC_OTHER;
+    private String[] _comments = null;
+    private int _listIndex = -1;
+    private int _srcMode = MODE_META | MODE_MAPPING;
+    private int _resMode = MODE_NONE;
+
+    private Class _type = Object.class;
+    private final Map _fieldMap = new TreeMap();
+    private Map _supFieldMap = null;
+    private boolean _defSupFields = false;
+    private Collection _staticFields = null;
+    private int[] _fieldDataTable = null;
+    private Map _fgMap = null;
+
+    ////////////////////////////////////////////////////////////////////
+    // Note: if you add additional state, make sure to add it to copy()
+    ////////////////////////////////////////////////////////////////////
+
+    private Class _objectId = null;
+    private Boolean _objectIdShared = null;
+    private Boolean _openjpaId = null;
+    private Boolean _extent = null;
+    private Boolean _embedded = null;
+    private Boolean _interface = null;
+    private Class _impl = null;
+    private List _interfaces = null;
+    private final Map _ifaceMap = new HashMap();
+    private int _identity = ID_UNKNOWN;
+    private int _idStrategy = ValueStrategies.NONE;
+    private int _accessType = ACCESS_UNKNOWN;
+
+    private String _seqName = DEFAULT_STRING;
+    private SequenceMetaData _seqMeta = null;
+    private String _cacheName = DEFAULT_STRING;
+    private int _cacheTimeout = Integer.MIN_VALUE;
+    private Boolean _detachable = null;
+    private String _detachState = DEFAULT_STRING;
+    private String _alias = null;
+    private int _versionIdx = Integer.MIN_VALUE;
+
+    private Class _super = null;
+    private ClassMetaData _superMeta = null;
+    private Class[] _subs = null;
+    private ClassMetaData[] _subMetas = null;
+    private ClassMetaData[] _mapSubMetas = null;
+
+    private FieldMetaData[] _fields = null;
+    private FieldMetaData[] _unmgdFields = null;
+    private FieldMetaData[] _allFields = null;
+    private FieldMetaData[] _allPKFields = null;
+    private FieldMetaData[] _allDFGFields = null;
+    private FieldMetaData[] _definedFields = null;
+    private FieldMetaData[] _listingFields = null;
+    private FieldMetaData[] _allListingFields = null;
+    private FetchGroup[] _fgs = null;
+    private FetchGroup[] _customFGs = null;
+    private boolean _intercepting = false;
+
+    private boolean _abstract = false;
+    
+    /**
+     * Constructor. Supply described type and repository.
+     */
+    protected ClassMetaData(Class type, MetaDataRepository repos) {
+        _repos = repos;
+        _owner = null;
+        setDescribedType(type);
+    }
+
+    /**
+     * Embedded constructor. Supply embedding value.
+     */
+    protected ClassMetaData(ValueMetaData owner) {
+        _owner = owner;
+        _repos = owner.getRepository();

[... 2172 lines stripped ...]