/*
 * 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.Collections;
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.Objects;
import java.util.Set;
import java.util.TreeMap;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.datacache.CacheDistributionPolicy;
import org.apache.openjpa.datacache.DataCache;
import org.apache.openjpa.enhance.PCRegistry;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.lib.conf.Value;
import org.apache.openjpa.lib.conf.ValueListener;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.SourceTracker;
import org.apache.openjpa.lib.util.ClassUtil;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.lib.xml.Commentable;
import org.apache.openjpa.util.BigDecimalId;
import org.apache.openjpa.util.BigIntegerId;
import org.apache.openjpa.util.BooleanId;
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.ImplHelper;
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;


/**
 * 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<ClassMetaData>, SourceTracker, MetaDataContext,
    MetaDataModes, Commentable, ValueListener {

    private static final long serialVersionUID = 1L;

    /**
     * Unknown 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 = AccessCode.UNKNOWN;

    /**
     * Persistent attributes are accessed via direct field access. Bit flag.
     */
    public static final int ACCESS_FIELD = AccessCode.FIELD;

    /**
     * Persistent attributes are accessed via setters and getters. Bit flag.
     */
    public static final int ACCESS_PROPERTY = AccessCode.PROPERTY;

    /**
     * Persistent class has explicitly defined an access type.
     * This will allow the attributes to use mixed access i.e. some field
     * may use ACCESS_FIELD while others ACCESS_PROPERTY.
     */
    public static final int ACCESS_EXPLICIT = AccessCode.EXPLICIT;

    /**
     * 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 String _srcName = null;
    private int _srcType = SRC_OTHER;
    private int _lineNum = 0;
    private int _colNum = 0;
    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 int _hashCode = Object.class.getName().hashCode();
    private String _typeString = Object.class.getName();
    private final Map<String,FieldMetaData> _fieldMap = new TreeMap<>();
    private Map<String,FieldMetaData> _supFieldMap = null;
    private boolean _defSupFields = false;
    private Collection<String> _staticFields = null;
    private int[] _fieldDataTable = null;
    private Map<String,FetchGroup> _fgMap = null;

    ////////////////////////////////////////////////////////////////////
    // Note: if you add additional state, make sure to add it to copy()
    ////////////////////////////////////////////////////////////////////

    private Class<?> _objectId = null;
    private Class<?> _idClass = null;
    private Boolean _objectIdShared = null;
    private Boolean _openjpaId = null;
    private Boolean _extent = null;
    private Boolean _embedded = null;
    private boolean _embeddable = false;
    private Boolean _interface = null;
    private Class<?> _impl = null;
    private List<Class<?>> _interfaces = null;
    private final Map<Class<?>,Map<String,String>> _ifaceMap =
    	new HashMap<>();
    private Integer _identity = null;
    private int _idStrategy = ValueStrategies.NONE;
    private int _accessType = AccessCode.UNKNOWN;

    private String _seqName = DEFAULT_STRING;
    private SequenceMetaData _seqMeta = null;
    private String _cacheName = DEFAULT_STRING; // null implies @DataCache(enabled=false)
    private boolean _dataCacheEnabled = false;     // true implies the class has been annotated by the user or name of
                                                // the cache is explicitly set by the user to a null string

    private Boolean _cacheEnabled = null;       // denotes status of JPA 2 @Cacheable annotation
    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 FieldMetaData[] _allProxyFields = null;
    private FieldMetaData[] _allLrsFields = null;
    private FetchGroup[] _fgs = null;
    private FetchGroup[] _customFGs = null;
    private boolean _intercepting = false;
    private Boolean _useIdClassFromParent = null;
    private boolean _abstract = false;
    private Boolean _hasAbstractPKField = null;
    private Boolean _hasPKFieldsFromAbstractClass = null;
    private int[] _pkAndNonPersistentManagedFmdIndexes = null;
    private Boolean inverseManagedFields = null;
    private List<FieldMetaData> _mappedByIdFields;
    private boolean _mappedByIdFieldsSet = false;
    private boolean _useSchemaElement = true;

    /**
     * Constructor. Supply described type and repository.
     */
    protected ClassMetaData(Class<?> type, MetaDataRepository repos) {
        _repos = repos;
        _owner = null;
        setDescribedType(type);
        registerForValueUpdate("DataCacheTimeout");
    }

    /**
     * Embedded constructor. Supply embedding value.
     */
    protected ClassMetaData(ValueMetaData owner) {
        _owner = owner;
        _repos = owner.getRepository();
        setEnvClassLoader(owner.getFieldMetaData().getDefiningMetaData().
            getEnvClassLoader());
        registerForValueUpdate("DataCacheTimeout");
    }

    /**
     * Return the owning repository.
     */
    @Override
    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;
    }

    /**
     * The persistence capable stringified class described by this metadata.
     */
    public String getDescribedTypeString(){
        return _typeString;
    }

    /**
     * Set the class described 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;
        _typeString = _type.getName();
        _hashCode = _typeString.hashCode();
        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 MetaDataRepository.EMPTY_CLASSES;

        _repos.processRegisteredClasses(_loader);
        if (_subs == null) {
            Collection<Class<?>> subs = _repos.getPCSubclasses(_type);
            _subs = 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<ClassMetaData> mapped =
                	new ArrayList<>(subs.length);
                for (int i = 0; i < subs.length; i++)
                    if (subs[i].isMapped())
                        mapped.add(subs[i]);
                _mapSubMetas = 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 != null) {
    		return _identity;
    	} else {
    		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 if (isAbstract())
	        	_identity = ID_UNKNOWN;
	        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 this entity does not use IdClass from the parent entity,
        // just return the _objectId set during annotation parsing time.
        if (!useIdClassFromParent()) {
            if (_objectId != null)
                return _objectId;
        }

        // if this entity uses IdClass from the parent entity,
        // the _objectId set during the parsing time should be
        // ignored, and let the system determine the objectId type
        // of this entity.
        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;
            case JavaTypes.BOOLEAN:
            case JavaTypes.BOOLEAN_OBJ:
                _objectId = BooleanId.class;
                break;
        }
        return _objectId;
    }

    /**
     * The metadata-specified class to use for the object ID.
     * When there is IdClass annotation, AnnotationMetaDataParser
     * will call this method to set ObjectId type. However, if
     * this is a derived identity in the child entity where a
     * relation field (parent entity) is used as an id, and this
     * relation field has an IdClass, the IdClass annotation in
     * the child entity can be ignored as Openjpa will automatically
     * wrap parent's IdClass as child's IdClass.
     */
    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;
                _idClass = 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;
        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;
    }

    /**
     * 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 = ClassUtil.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.
     *
     */
    public int getAccessType() {
        return _accessType;
    }

    /**
     * Sets the access type.
     */
    public void setAccessType(int type) {
    	if (type == _accessType || type == AccessCode.UNKNOWN)
    		return;
    	if (!AccessCode.isValidClassCode(type)) {
            throw new IllegalArgumentException(_loc.get("access-type-invalid",
    		    this, AccessCode.toClassString(type)).getMessage());
    	}
    	if (_accessType != AccessCode.UNKNOWN) { // changing access type
    	    _repos.getLog().trace(_loc.get("access-type-change",
    		    this, AccessCode.toClassString(type),
    		    AccessCode.toClassString(_accessType)).getMessage());
    	}
        _accessType = type;
    }

    /**
     * Asserts the the given field (which must belong to this receiver)
     * can be set to the given access code. If the field code is allowed,
     * it may have the side-effect of changing the access code of this receiver.
     */
    void mergeFieldAccess(FieldMetaData fmd, int fCode) {
    	setAccessType(AccessCode.mergeFieldCode(this, fmd, fCode));
    }

    /**
     * Affirms if access style is explicitly defined.
     */
    public boolean isExplicitAccess() {
        return AccessCode.isExplicit(_accessType);
    }

    /**
     * Affirms if attributes of this class use mixed access types.
     */
    public boolean isMixedAccess() {
    	return AccessCode.isMixed(_accessType);
    }

    /**
     * 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;
    }

    /**
     * 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;
    }

    /**
     * Whether the type can only be used as an embedded object.
     */
    public void setEmbeddedOnly(boolean embed) {
        _embedded = (embed) ? Boolean.TRUE : Boolean.FALSE;
    }

    public boolean isEmbeddable() {
        return _embeddable;
    }

    public void setEmbeddable() {
        _embeddable = true;
    }

    /**
     * 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;
    }

    /**
     * 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(AccessCode.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 _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<String, String> fields = _ifaceMap.computeIfAbsent(iface, k -> new HashMap<>());
            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<String,String> fields = _ifaceMap.get(iface);
            if (fields == null)
                return null;
            return fields.get(orig);
        }
    }

    /**
     * Return all aliases property named for the given interface.
     */
    public String[] getInterfaceAliasedProperties(Class<?> iface) {
        synchronized (_ifaceMap) {
            Map<String,String> fields = _ifaceMap.get(iface);
            if (fields == null)
                return EMPTY_STRING_ARRAY;
            return 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 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) {
        int[] array = getExtraFieldDataTable();
        if (field < 0 || field >= array.length)
            return -1;
        return array[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 = AccessController.doPrivileged(
                J2DoPrivHelper.getDeclaredFieldsAction(_type));
            Set<String> names = new HashSet<>();
            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 fields that are types that need to be wrappered by a proxy.
     * The types that need to be proxied are:
     * <p>
     *  <li>org.apache.openjpa.meta.JavaTypes.CALENDAR
     *  <li>org.apache.openjpa.meta.JavaTypes.COLLECTION
     *  <li>org.apache.openjpa.meta.JavaTypes.DATE
     *  <li>org.apache.openjpa.meta.JavaTypes.MAP
     *  <li>org.apache.openjpa.meta.JavaTypes.OBJECT
     */
    public FieldMetaData[] getProxyFields() {
        if (_allProxyFields == null) {
            // Make sure _allFields has been initialized
            if (_allFields == null) {
                getFields();
            }
            List<FieldMetaData> res = new ArrayList<>();
            for (FieldMetaData fmd : _allFields) {
                switch (fmd.getDeclaredTypeCode()) {
                    case JavaTypes.CALENDAR:
                    case JavaTypes.COLLECTION:
                    case JavaTypes.DATE:
                    case JavaTypes.MAP:
                    case JavaTypes.OBJECT:
                        res.add(fmd);
                        break;
                }
            }
            _allProxyFields = res.toArray(new FieldMetaData[res.size()]);
        }
        return _allProxyFields;
    }

    /**
     * Return all large result set fields. Will never return null.
     */
    public FieldMetaData[] getLrsFields() {
        if (_allLrsFields == null) {
            // Make sure _allFields has been initialized
            if (_allFields == null) {
                getFields();
            }
            List<FieldMetaData> res = new ArrayList<>();
            for (FieldMetaData fmd : _allFields) {
                if(fmd.isLRS()){
                    res.add(fmd);
                }
            }
            _allLrsFields = res.toArray(new FieldMetaData[res.size()]);
        }
        return _allLrsFields;
    }

    /**
     * Return all field metadata, 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 = _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() != FieldMetaData.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<FieldMetaData> fields =
            	new ArrayList<>(_fieldMap.size());
            for (FieldMetaData fmd : _fieldMap.values()) {
                if (fmd.getManagement() != FieldMetaData.MANAGE_NONE) {
                    fmd.setDeclaredIndex(fields.size());
                    fmd.setIndex(fmd.getDeclaredIndex());
                    fields.add(fmd);
                }
            }
            _fields = 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 primary key fields even if not set to ID_APPLICATION so
        // that Application Id tool sees them even when user doesn't declare
    	// Application identity
        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 (_allFields == null) {
            getFields();
        }
        if (_versionIdx == Integer.MIN_VALUE) {
            int idx = -1;
            for (int i = 0; i < _allFields.length; i++) {
                if (_allFields[i].isVersion()) {
                    if (idx != -1)
                        throw new MetaDataException(_loc.get("mult-vers-fields", this, _allFields[idx], _allFields[i]));
                    idx = i;
                }
            }
            _versionIdx = idx;
        }
        if (_versionIdx == -1)
            return null;

        return _allFields[_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) {
        if(_allFields == null){
            getFields();
        }
        if (index < 0 || index >= _allFields.length)
            return null;
        return _allFields[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 = _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 = _fieldMap.get(name);
        if (field == null || field.getManagement() == FieldMetaData.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) {
            List<FieldMetaData> unmanaged = new ArrayList<>(3);
            for (FieldMetaData field : _fieldMap.values()) {
                if (field.getManagement() == FieldMetaData.MANAGE_NONE)
                    unmanaged.add(field);
            }
            _unmgdFields = 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 _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 sup;
        for (FieldMetaData fmd : _supFieldMap.values()) {
            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<FieldMetaData> defined =
            	new ArrayList<>(fields.length);
            for (FieldMetaData fmd : fields) {
                if (fmd.isMapped()
                    && fmd.getDefiningMetaData() == this)
                    defined.add(fmd);
            }
            _definedFields = 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<FieldMetaData> defined =
            	new ArrayList<>(fields.length);
            for (FieldMetaData fmd : fields)
                if (fmd.getDefiningMetaData() == this)
                    defined.add(fmd);
            FieldMetaData[] unmgd = getDeclaredUnmanagedFields();
            FieldMetaData[] listing = _repos.newFieldMetaDataArray
                (defined.size() + unmgd.length);
            for (int i = 0; i < defined.size(); i++)
                listing[i] = 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 data cache that stores the managed instance of this class, by default.
     * This can be overwritten by per-instance basis {@linkplain CacheDistributionPolicy cache distribution policy}.
     *
     * @return null if this class is disabled from cache by @DataCache(enabled=false).
     *         {@linkplain DataCache#NAME_DEFAULT default} if @DataCache(enabled=true) without a name.
     *         Otherwise, data cache name set by the user via @DataCache name attribute.
     *
     */
    public String getDataCacheName() {
        if (DEFAULT_STRING.equals(_cacheName)) {
            if (_super != null && StringUtil.isNotEmpty(getPCSuperclassMetaData().getDataCacheName())) {
                _cacheName = getPCSuperclassMetaData().getDataCacheName();
            } else {
                _cacheName = DataCache.NAME_DEFAULT;
            }
        }
        return _cacheName;
    }

    /**
     * Set the cache name for this class.
     *
     * @param name can be {@code null} to disable cache.
     */
    public void setDataCacheName(String name) {
        _cacheName = name;
        if (name != null)
            _dataCacheEnabled = true;
    }

    /**
     * Affirms true if this receiver is annotated with @DataCache and is not disabled.
     * A separate state variable is necessary besides the name of the cache defaulted to a special string.
     */
    public boolean getDataCacheEnabled() {
        return _dataCacheEnabled;
    }

    /**
     * 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;
    }

    /**
     * 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;
        _allProxyFields = null;
        _allLrsFields = 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();
    }

    @Override
    public int hashCode() {
        return _hashCode;
    }

    @Override
    public boolean equals(Object other) {
        if (other == this)
            return true;
        if (!(other instanceof ClassMetaData))
            return false;
        return _type == ((ClassMetaData) other).getDescribedType();
    }

    @Override
    public int compareTo(ClassMetaData other) {
        if (other == this)
            return 0;
        return _type.getName().compareTo(other.
            getDescribedType().getName());
    }

    @Override
    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 & MetaDataRepository.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 & MetaDataRepository.VALIDATE_META) != 0)
                validateMeta(runtime);
        }
        if ((mode & MODE_MAPPING) != 0 && (cur & MODE_MAPPING) == 0) {
            resolveMapping(runtime);
            if (validate && (val & MetaDataRepository.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 (recursiveEmbed(_owner)) {
                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<FieldMetaData> 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 = 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(FieldMetaData.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 (Class<?> iface : _interfaces)
                _repos.addDeclaredInterfaceImpl(this, iface);
        }

        // resolve fetch groups
        if (_fgMap != null)
            for (FetchGroup fg : _fgMap.values())
                fg.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);
        }
    }

    private boolean recursiveEmbed(ValueMetaData owner) {
        ClassMetaData cm = owner.getFieldMetaData().getDefiningMetaData();
        if (cm.getDescribedType().isAssignableFrom(_type))
            return true;
        ValueMetaData owner1 = cm.getEmbeddingMetaData();
        if (owner1 == null)
            return false;
        else
            return recursiveEmbed(owner1);
    }

    /**
     * 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 (!StringUtil.isEmpty(superCache)) {
            if (!Objects.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<String> 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,
            		Arrays.asList(toNames(pks))));
        }
        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 oid must match or be parent of ours
            ClassMetaData sup = getPCSuperclassMetaData();
            Class<?> objectIdType = sup.getObjectIdType();
            if (objectIdType != null &&
                !objectIdType.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 application id class has all primary key fields
            validateAppIdClassPKs(this, pks, _objectId);
        }
    }
    /**
     * Return true if this class uses IdClass derived from idClass of the
     * parent entity which annotated as id in the child class.
     * In this case, there are no key fields in the child entity corresponding
     * to the fields in the IdClass.
     */
    public boolean useIdClassFromParent() {
        if (_useIdClassFromParent == null) {
            if (_objectId == null)
                _useIdClassFromParent = false;
            else {
                FieldMetaData[] pks = getPrimaryKeyFields();
                if (pks.length != 1)
                    _useIdClassFromParent = false;
                else {
                    ClassMetaData pkMeta = pks[0].getTypeMetaData();
                    if (pkMeta == null)
                        _useIdClassFromParent = false;
                    else {
                        Class<?> pkType = pkMeta.getObjectIdType();
                        if (pkType == ObjectId.class) //parent id is EmbeddedId
                            pkType = pkMeta.getPrimaryKeyFields()[0].getType();
                        if (pkType == _objectId)
                            _useIdClassFromParent = true;
                        else {
                            Field f = Reflection.findField(_objectId,
                                pks[0].getName(), false);
                            if (f != null)
                                _useIdClassFromParent = false;
                            else
                                throw new MetaDataException(_loc.get(
                                        "invalid-id", _type, pks[0].getName()));
                        }
                    }
                }
            }
        }
        return _useIdClassFromParent;
    }

    /**
     * Return true if this class has a concrete persistent superclass.
     */
    private boolean hasConcretePCSuperclass() {
        if (_super == null)
            return false;
        if (!Modifier.isAbstract(_super.getModifiers()) &&
        		(!getPCSuperclassMetaData().isAbstract()))
            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", oid, _type)).
                setCause(e);
        }

        // check for equals and hashcode overrides; don't enforce it
        // for abstract application 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 (AccessCode.isField(fmds[i].getAccessType())) {
                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 (AccessCode.isProperty(fmds[i].getAccessType())) {
                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.
     * If no access style is set or an explicit style is set return.
     * Otherwise, if the superclass has persistent attributes,  check that
     * the superclass access style, if defaulted, is the same as that of this
     * receiver.
     */
    private void validateAccessType() {
        if (AccessCode.isEmpty(_accessType)
           || AccessCode.isExplicit(_accessType))
            return;
        ClassMetaData sup = getPCSuperclassMetaData();
        while (sup != null && sup.isExplicitAccess())
        	sup = sup.getPCSuperclassMetaData();
        if (sup != null && sup.getDeclaredFields().length > 0) {
        	int supCode = sup.getAccessType();
        	if (!AccessCode.isCompatibleSuper(_accessType, supCode))
             throw new MetaDataException(_loc.get("access-inconsistent-inherit",
             new Object[]{this, AccessCode.toClassString(_accessType),
                          sup, AccessCode.toClassString(supCode)}).toString());
        }
    }

    /**
     * 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 : _fgMap.values().toArray(new FetchGroup[_fgMap.size()]);
        }
        return _fgs;
    }

    /**
     * Return all fetch groups for this type, including superclass groups but excluding the standard groups
     * such as "default" or "all".
     */
    public FetchGroup[] getCustomFetchGroups() {
        if (_customFGs == null) {
            // map fetch groups to names, allowing our groups to override super
            Map<String,FetchGroup> 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 standard groups
            fgs.remove(FetchGroup.NAME_DEFAULT);
            fgs.remove(FetchGroup.NAME_ALL);

            _customFGs = fgs.values().toArray(new FetchGroup[fgs.size()]);
        }
        return _customFGs;
    }

    /**
     * Gets a named fetch group. If not available in this receiver then looks
     * up the inheritance hierarchy.
     *
     * @param name name of a fetch group.
     * @return an existing fetch 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 : _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 (StringUtil.isEmpty(name))
    		throw new MetaDataException(_loc.get("empty-fg-name", this));
        if (_fgMap == null)
            _fgMap = new HashMap<>();
        FetchGroup fg = _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
    /////////////////

    @Override
    public File getSourceFile() {
        return _srcFile;
    }

    @Override
    public Object getSourceScope() {
        return null;
    }

    @Override
    public int getSourceType() {
        return _srcType;
    }

    public void setSource(File file, int srcType, String srcName) {
        _srcFile = file;
        _srcType = srcType;
        _srcName = srcName;
    }

    @Override
    public String getResourceName() {
        return _type.getName();
    }

    @Override
    public int getLineNumber() {
        return _lineNum;
    }

    public void setLineNumber(int lineNum) {
        _lineNum = lineNum;
    }

    @Override
    public int getColNumber() {
        return _colNum;
    }

    public void setColNumber(int colNum) {
        _colNum = colNum;
    }


    /**
     * 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
    ///////////////

    @Override
    public String[] getComments() {
        return (_comments == null) ? EMPTY_COMMENTS : _comments;
    }

    @Override
    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();
        _idClass = meta.getIdClass();
        _extent = (meta.getRequiresExtent()) ? Boolean.TRUE : Boolean.FALSE;
        _embedded = (meta.isEmbeddedOnly()) ? Boolean.TRUE : Boolean.FALSE;
        _embeddable = meta._embeddable;
        _interface = (meta.isManagedInterface()) ? Boolean.TRUE : Boolean.FALSE;
        setIntercepting(meta.isIntercepting());
        _abstract = meta.isAbstract();
        _impl = meta.getInterfaceImpl();
        _identity = meta._identity == null ? null : 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();
        _cacheEnabled = meta.getCacheEnabled();
        _dataCacheEnabled = meta.getDataCacheEnabled();
        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 interface 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);
    }

    @Override
    protected void addExtensionKeys(Collection exts) {
        _repos.getMetaDataFactory().addClassExtensionKeys(exts);
    }

    /**
     * Comparator used to put field metadata into listing order.
     */
    private static class ListingOrderComparator
        implements Comparator<FieldMetaData> {

        private static final ListingOrderComparator _instance
            = new ListingOrderComparator();

        /**
         * Access singleton instance.
         */
        public static ListingOrderComparator getInstance() {
            return _instance;
        }

        @Override
        public int compare(FieldMetaData f1, FieldMetaData f2) {
            if (f1 == f2)
                return 0;
            if (f1 == null)
                return 1;
            if (f2 == null)
                return -1;

            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 ();
		}
	}

    public void registerForValueUpdate(String...values) {
    	if (values == null)
    		return;
    	for (String key : values) {
    		Value value = getRepository().getConfiguration()
    			.getValue(key);
    		if (value != null)
    			value.addListener(this);
    	}
    }

    @Override
    public void valueChanged(Value val) {
    	if (val != null && val.matches("DataCacheTimeout")) {
    		_cacheTimeout = Integer.MIN_VALUE;
    	}
    }

    /**
     * Utility method to get names of all fields including the superclasses'
     * sorted in lexical order.
     */
    public String[] getFieldNames() {
    	return toNames(getFields());
    }

    /**
     * Utility method to get names of all declared fields excluding the
     * superclasses' sorted in lexical order.
     */
    public String[] getDeclaredFieldNames() {
    	return toNames(getDeclaredFields());
    }

    String[] toNames(FieldMetaData[] fields) {
    	List<String> result = new ArrayList<>();
    	for (FieldMetaData fmd : fields) {
    		result.add(fmd.getName());
    	}
    	Collections.sort(result);
    	return result.toArray(new String[result.size()]);
    }


    public boolean isAbstract() {
        return _abstract;
    }

    public void setAbstract(boolean flag) {
        _abstract = flag;
    }

    /**
     * Convenience method to determine if the pcType modeled by
     * this ClassMetaData object is both abstract and declares PKFields. This
     * method is used by the PCEnhancer to determine if special handling is
     * required.
     *
     */
    public boolean hasAbstractPKField() {
        if (_hasAbstractPKField != null) {
            return _hasAbstractPKField;
        }

        // Default to false, set to true only if this type is abstract and
        // declares a PKField.
        Boolean temp = Boolean.FALSE;

        if (isAbstract()) {
            FieldMetaData[] declaredFields = getDeclaredFields();
            if (declaredFields != null && declaredFields.length != 0) {
                for (FieldMetaData fmd : declaredFields) {
                    if (fmd.isPrimaryKey()) {
                        temp = Boolean.TRUE;
                        break;
                    }
                }
            }
        }
        _hasAbstractPKField = temp;

        return _hasAbstractPKField;
    }

    /**
     * Convenience method to determine if this type is a direct
     * decendent of an abstract type declaring PKFields. Returns true if there
     * are no pcTypes mapped to a table between this type and an abstract pcType
     * declaring PKFields. Returns false if there no such abstract pcTypes in
     * the inheritance hierarchy or if there are any pcTypes mapped to tables in
     * between the type represented by this ClassMetaData object and the
     * abstract pcType declaring PKFields.
     *
     */
    public boolean hasPKFieldsFromAbstractClass() {
        if (_hasPKFieldsFromAbstractClass != null) {
            return _hasPKFieldsFromAbstractClass;
        }

        // Default to FALSE, until proven true.
        Boolean temp = Boolean.FALSE;

        FieldMetaData[] pkFields = getPrimaryKeyFields();
        for (FieldMetaData fmd : pkFields) {
            ClassMetaData fmdDMDA = fmd.getDeclaringMetaData();
            if (fmdDMDA.isAbstract()) {
                ClassMetaData cmd = getPCSuperclassMetaData();
                while (cmd != fmdDMDA) {
                    if (fmdDMDA.isAbstract()) {
                        cmd = cmd.getPCSuperclassMetaData();
                    } else {
                        break;
                    }
                }
                if (cmd == fmdDMDA) {
                    temp = Boolean.TRUE;
                    break;
                }
            }
        }
        _hasPKFieldsFromAbstractClass = temp;

        return _hasPKFieldsFromAbstractClass;
    }

    /**
     * Sets the eligibility status of this class for cache.
     *
     */
    public void setCacheEnabled(boolean enabled) {
        _cacheEnabled = enabled;
    }

    /**
     * Returns tri-state status on whether this class has been enabled for caching.
     *
     * @return TRUE or FALSE denote this class has been explicitly enabled or disabled for caching.
     * If no status has been explicitly set, then the status of the persistent super class, if any, is returned.
     */
    public Boolean getCacheEnabled() {
        if (_cacheEnabled != null)
            return _cacheEnabled;
        return getPCSuperclassMetaData() != null ?  getPCSuperclassMetaData().getCacheEnabled() : null;
    }

    public String getSourceName(){
        return _srcName;
    }

    public int[] getPkAndNonPersistentManagedFmdIndexes() {
        if (_pkAndNonPersistentManagedFmdIndexes == null) {
            List<Integer> ids = new ArrayList<>();
            for (FieldMetaData fmd : getFields()) {
                if (fmd.isPrimaryKey() || fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT) {
                    ids.add(fmd.getIndex());
                }
            }
            int idsSize = ids.size();
            int[] temp = new int[idsSize];
            for (int i = 0; i < idsSize; i++) {
                temp[i] = ids.get(i);
            }
            _pkAndNonPersistentManagedFmdIndexes = temp;
        }
        return _pkAndNonPersistentManagedFmdIndexes;
    }

    public boolean hasInverseManagedFields() {
        if (inverseManagedFields == null) {
            Boolean res = Boolean.FALSE;
            for (FieldMetaData fmd : getFields()) {
                if (fmd.getInverseMetaDatas().length > 0) {
                    res = Boolean.TRUE;
                    break;
                }
            }
            inverseManagedFields = res;
        }
        return inverseManagedFields;
    }

    public List<FieldMetaData> getMappyedByIdFields() {
        if (!_mappedByIdFieldsSet) {
            List<FieldMetaData> fmdArray = null;
            for (FieldMetaData fmd : getFields()) {
                if (getIdentityType() == ClassMetaData.ID_APPLICATION) {
                    String mappedByIdValue = fmd.getMappedByIdValue();
                    if (mappedByIdValue != null) {
                        if (fmdArray == null) {
                            fmdArray = new ArrayList<>();
                        }
                        fmdArray.add(fmd);
                    }
                }
            }
            _mappedByIdFields = fmdArray;
            _mappedByIdFieldsSet = true;
        }
        return _mappedByIdFields;
    }

    /**
     * Set whether to include schema name in generated class files
     */
    public boolean getUseSchemaElement() {
        return _useSchemaElement;
    }

    /**
     * Get whether to include schema name in generated class files
     */
    public void setUseSchemaElement(boolean useSchemaElement) {
        this._useSchemaElement = useSchemaElement;
    }

    /**
     * The class specified with the @IdClass annotation if used
     */
    public Class<?> getIdClass() {
        return _idClass;
    }
}
