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

import static javax.persistence.GenerationType.AUTO;
import static org.apache.openjpa.persistence.MetaDataTag.ACCESS;
import static org.apache.openjpa.persistence.MetaDataTag.CACHEABLE;
import static org.apache.openjpa.persistence.MetaDataTag.DATASTORE_ID;
import static org.apache.openjpa.persistence.MetaDataTag.DATA_CACHE;
import static org.apache.openjpa.persistence.MetaDataTag.DEPENDENT;
import static org.apache.openjpa.persistence.MetaDataTag.DETACHED_STATE;
import static org.apache.openjpa.persistence.MetaDataTag.ELEM_DEPENDENT;
import static org.apache.openjpa.persistence.MetaDataTag.ELEM_TYPE;
import static org.apache.openjpa.persistence.MetaDataTag.EMBEDDED_ID;
import static org.apache.openjpa.persistence.MetaDataTag.ENTITY_LISTENERS;
import static org.apache.openjpa.persistence.MetaDataTag.EXCLUDE_DEFAULT_LISTENERS;
import static org.apache.openjpa.persistence.MetaDataTag.EXCLUDE_SUPERCLASS_LISTENERS;
import static org.apache.openjpa.persistence.MetaDataTag.EXTERNALIZER;
import static org.apache.openjpa.persistence.MetaDataTag.EXTERNAL_VALS;
import static org.apache.openjpa.persistence.MetaDataTag.FACTORY;
import static org.apache.openjpa.persistence.MetaDataTag.FETCH_GROUP;
import static org.apache.openjpa.persistence.MetaDataTag.FETCH_GROUPS;
import static org.apache.openjpa.persistence.MetaDataTag.FLUSH_MODE;
import static org.apache.openjpa.persistence.MetaDataTag.GENERATED_VALUE;
import static org.apache.openjpa.persistence.MetaDataTag.ID;
import static org.apache.openjpa.persistence.MetaDataTag.ID_CLASS;
import static org.apache.openjpa.persistence.MetaDataTag.INVERSE_LOGICAL;
import static org.apache.openjpa.persistence.MetaDataTag.KEY_DEPENDENT;
import static org.apache.openjpa.persistence.MetaDataTag.KEY_TYPE;
import static org.apache.openjpa.persistence.MetaDataTag.LOAD_FETCH_GROUP;
import static org.apache.openjpa.persistence.MetaDataTag.LRS;
import static org.apache.openjpa.persistence.MetaDataTag.MANAGED_INTERFACE;
import static org.apache.openjpa.persistence.MetaDataTag.MAPPED_BY_ID;
import static org.apache.openjpa.persistence.MetaDataTag.MAP_KEY;
import static org.apache.openjpa.persistence.MetaDataTag.MAP_KEY_CLASS;
import static org.apache.openjpa.persistence.MetaDataTag.NATIVE_QUERIES;
import static org.apache.openjpa.persistence.MetaDataTag.NATIVE_QUERY;
import static org.apache.openjpa.persistence.MetaDataTag.ORDER_BY;
import static org.apache.openjpa.persistence.MetaDataTag.POST_LOAD;
import static org.apache.openjpa.persistence.MetaDataTag.POST_PERSIST;
import static org.apache.openjpa.persistence.MetaDataTag.POST_REMOVE;
import static org.apache.openjpa.persistence.MetaDataTag.POST_UPDATE;
import static org.apache.openjpa.persistence.MetaDataTag.PRE_PERSIST;
import static org.apache.openjpa.persistence.MetaDataTag.PRE_REMOVE;
import static org.apache.openjpa.persistence.MetaDataTag.PRE_UPDATE;
import static org.apache.openjpa.persistence.MetaDataTag.QUERIES;
import static org.apache.openjpa.persistence.MetaDataTag.QUERY;
import static org.apache.openjpa.persistence.MetaDataTag.READ_ONLY;
import static org.apache.openjpa.persistence.MetaDataTag.SEQ_GENERATOR;
import static org.apache.openjpa.persistence.MetaDataTag.STOREDPROCEDURE_QUERIES;
import static org.apache.openjpa.persistence.MetaDataTag.STOREDPROCEDURE_QUERY;
import static org.apache.openjpa.persistence.MetaDataTag.TYPE;
import static org.apache.openjpa.persistence.MetaDataTag.VERSION;

import java.io.File;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;

import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Basic;
import javax.persistence.Cacheable;
import javax.persistence.CascadeType;
import javax.persistence.Convert;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.ExcludeDefaultListeners;
import javax.persistence.ExcludeSuperclassListeners;
import javax.persistence.FetchType;
import javax.persistence.FlushModeType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.Lob;
import javax.persistence.LockModeType;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
import javax.persistence.MapKeyClass;
import javax.persistence.MappedSuperclass;
import javax.persistence.MapsId;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.NamedStoredProcedureQueries;
import javax.persistence.NamedStoredProcedureQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.ParameterMode;
import javax.persistence.PostLoad;
import javax.persistence.PostPersist;
import javax.persistence.PostRemove;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreRemove;
import javax.persistence.PreUpdate;
import javax.persistence.QueryHint;
import javax.persistence.SequenceGenerator;
import javax.persistence.StoredProcedureParameter;
import javax.persistence.Version;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.event.BeanLifecycleCallbacks;
import org.apache.openjpa.event.LifecycleCallbacks;
import org.apache.openjpa.event.LifecycleEvent;
import org.apache.openjpa.event.MethodLifecycleCallbacks;
import org.apache.openjpa.kernel.QueryLanguages;
import org.apache.openjpa.kernel.jpql.JPQLParser;
import org.apache.openjpa.lib.conf.Configurations;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.SourceTracker;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.meta.AccessCode;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.DelegatingMetaDataFactory;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.LifecycleMetaData;
import org.apache.openjpa.meta.MetaDataFactory;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.MultiQueryMetaData;
import org.apache.openjpa.meta.Order;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.meta.SequenceMetaData;
import org.apache.openjpa.meta.UpdateStrategies;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.meta.ValueStrategies;
import org.apache.openjpa.util.ImplHelper;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UnsupportedException;
import org.apache.openjpa.util.UserException;
import static org.apache.openjpa.persistence.MetaDataTag.CONVERT;


/**
 * Persistence annotation metadata parser. Currently does not parse
 * deployment descriptors.
 *
 * @author Abe White
 * @author Steve Kim
 */
public class AnnotationPersistenceMetaDataParser
    implements MetaDataModes {

    private static final Localizer _loc = Localizer.forPackage
        (AnnotationPersistenceMetaDataParser.class);

    private static final Map<Class<?>, MetaDataTag> _tags =
        new HashMap<>();

    static {
        _tags.put(Access.class, ACCESS);
        _tags.put(Cacheable.class, CACHEABLE);
        _tags.put(EmbeddedId.class, EMBEDDED_ID);
        _tags.put(EntityListeners.class, ENTITY_LISTENERS);
        _tags.put(ExcludeDefaultListeners.class, EXCLUDE_DEFAULT_LISTENERS);
        _tags.put(ExcludeSuperclassListeners.class,
            EXCLUDE_SUPERCLASS_LISTENERS);
        _tags.put(FlushModeType.class, FLUSH_MODE);
        _tags.put(GeneratedValue.class, GENERATED_VALUE);
        _tags.put(Id.class, ID);
        _tags.put(IdClass.class, ID_CLASS);
        _tags.put(MapKey.class, MAP_KEY);
        _tags.put(MapKeyClass.class, MAP_KEY_CLASS);
        _tags.put(MapsId.class, MAPPED_BY_ID);
        _tags.put(NamedNativeQueries.class, NATIVE_QUERIES);
        _tags.put(NamedNativeQuery.class, NATIVE_QUERY);
        _tags.put(NamedStoredProcedureQueries.class, STOREDPROCEDURE_QUERIES);
        _tags.put(NamedStoredProcedureQuery.class, STOREDPROCEDURE_QUERY);
        _tags.put(NamedQueries.class, QUERIES);
        _tags.put(NamedQuery.class, QUERY);
        _tags.put(OrderBy.class, ORDER_BY);
        _tags.put(PostLoad.class, POST_LOAD);
        _tags.put(PostPersist.class, POST_PERSIST);
        _tags.put(PostRemove.class, POST_REMOVE);
        _tags.put(PostUpdate.class, POST_UPDATE);
        _tags.put(PrePersist.class, PRE_PERSIST);
        _tags.put(PreRemove.class, PRE_REMOVE);
        _tags.put(PreUpdate.class, PRE_UPDATE);
        _tags.put(SequenceGenerator.class, SEQ_GENERATOR);
        _tags.put(Version.class, VERSION);
        _tags.put(DataCache.class, DATA_CACHE);
        _tags.put(DataStoreId.class, DATASTORE_ID);
        _tags.put(Dependent.class, DEPENDENT);
        _tags.put(DetachedState.class, DETACHED_STATE);
        _tags.put(ElementDependent.class, ELEM_DEPENDENT);
        _tags.put(ElementType.class, ELEM_TYPE);
        _tags.put(ExternalValues.class, EXTERNAL_VALS);
        _tags.put(Externalizer.class, EXTERNALIZER);
        _tags.put(Convert.class, CONVERT);
        _tags.put(Factory.class, FACTORY);
        _tags.put(FetchGroup.class, FETCH_GROUP);
        _tags.put(FetchGroups.class, FETCH_GROUPS);
        _tags.put(InverseLogical.class, INVERSE_LOGICAL);
        _tags.put(KeyDependent.class, KEY_DEPENDENT);
        _tags.put(KeyType.class, KEY_TYPE);
        _tags.put(LoadFetchGroup.class, LOAD_FETCH_GROUP);
        _tags.put(LRS.class, LRS);
        _tags.put(ManagedInterface.class, MANAGED_INTERFACE);
        _tags.put(ReadOnly.class, READ_ONLY);
        _tags.put(Type.class, TYPE);
    }

    private final OpenJPAConfiguration _conf;
    private final Log _log;
    private MetaDataRepository _repos = null;
    private ClassLoader _envLoader = null;
    private boolean _override = false;
    private int _mode = MODE_NONE;

    // packages and their parse modes
    private final Map<Package, Integer> _pkgs = new HashMap<>();

    // the class we were invoked to parse
    protected Class<?> _cls = null;
    protected Stack<Class<?>> _stack = new Stack<>();
    private File _file = null;

    /**
     * Constructor; supply configuration.
     */
    public AnnotationPersistenceMetaDataParser(OpenJPAConfiguration conf) {
        _conf = conf;
        _log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
    }

    /**
     * Configuration supplied on construction.
     */
    public OpenJPAConfiguration getConfiguration() {
        return _conf;
    }

    /**
     * Metadata log.
     */
    public Log getLog() {
        return _log;
    }

    /**
     * Returns the repository for this parser. If none has been set,
     * create a new repository and sets it.
     */
    public MetaDataRepository getRepository() {
        if (_repos == null) {
            MetaDataRepository repos = _conf.newMetaDataRepositoryInstance();
            MetaDataFactory mdf = repos.getMetaDataFactory();
            if (mdf instanceof DelegatingMetaDataFactory)
                mdf = ((DelegatingMetaDataFactory) mdf).getInnermostDelegate();
            if (mdf instanceof PersistenceMetaDataFactory)
                ((PersistenceMetaDataFactory) mdf).setAnnotationParser(this);
            _repos = repos;
        }
        return _repos;
    }

    /**
     * Set the metadata repository for this parser.
     */
    public void setRepository(MetaDataRepository repos) {
        _repos = repos;
    }

    /**
     * Return the environmental class loader to pass on to parsed
     * metadata instances.
     */
    public ClassLoader getEnvClassLoader() {
        return _envLoader;
    }

    /**
     * Set the environmental class loader to pass on to parsed
     * metadata instances.
     */
    public void setEnvClassLoader(ClassLoader loader) {
        _envLoader = loader;
    }

    /**
     * Whether to allow later parses of mapping information to override
     * earlier information for the same class. Defaults to false. Useful
     * when a tool is mapping a class, so that annotation partial mapping
     * information can be used even when mappings are stored in another
     * location.
     */
    public boolean getMappingOverride() {
        return _override;
    }

    /**
     * Whether to allow later parses of mapping information to override
     * earlier information for the same class. Defaults to false. Useful
     * when a tool is mapping a class, so that annotation partial mapping
     * information can be used even when mappings are stored in another
     * location.
     */
    public void setMappingOverride(boolean override) {
        _override = override;
    }

    /**
     * The parse mode.
     */
    public int getMode() {
        return _mode;
    }

    /**
     * The parse mode.
     */
    public void setMode(int mode, boolean on) {
        if (mode == MODE_NONE)
            _mode = MODE_NONE;
        else if (on)
            _mode |= mode;
        else
            _mode &= ~mode;
    }

    /**
     * The parse mode.
     */
    public void setMode(int mode) {
        _mode = mode;
    }

    /**
     * Convenience method for interpreting {@link #getMode}.
     */
    protected boolean isMetaDataMode() {
        return (_mode & MODE_META) != 0;
    }

    /**
     * Convenience method for interpreting {@link #getMode}.
     */
    protected boolean isQueryMode() {
        return (_mode & MODE_QUERY) != 0;
    }

    /**
     * Convenience method for interpreting {@link #getMode}.
     */
    protected boolean isMappingMode() {
        return (_mode & MODE_MAPPING) != 0;
    }

    /**
     * Returns true if we're in mapping mode or in metadata mode with
     * mapping overide enabled.
     */
    protected boolean isMappingOverrideMode() {
        return isMappingMode() || (_override && isMetaDataMode());
    }

    /**
     * Clear caches.
     */
    public void clear() {
    	_stack.clear();
        _cls = null;
        _file = null;
        _pkgs.clear();
    }

    /**
     * Parse persistence metadata for the given class.
     */
    public void parse(Class<?> cls) {
        if (_log.isTraceEnabled())
            _log.trace(_loc.get("parse-class", cls.getName()));

        _cls = cls;
        _stack.push(cls);
        try {
            parsePackageAnnotations();
            ClassMetaData meta = parseClassAnnotations();
            updateSourceMode(meta);
        } finally {
        	_stack.pop();
            _cls = _stack.isEmpty() ? null : _stack.peek();
            _file = null;
        }
    }

    /**
     * Update the source mode to the class package and class to indicate that
     * we've fully parsed them.
     */
    private void updateSourceMode(ClassMetaData meta) {
        if (_cls.getPackage() != null)
            addSourceMode(_cls.getPackage(), _mode);
        if (meta != null)
            meta.setSourceMode(_mode, true);
    }

    /**
     * Parse information in package-level class annotations.
     */
    private void parsePackageAnnotations() {
        Package pkg = _cls.getPackage();
        if (pkg == null)
            return;

        int pkgMode = getSourceMode(pkg);
        if (pkgMode == 0 && _log.isTraceEnabled())
            _log.trace(_loc.get("parse-package", _cls.getName()));
        if ((pkgMode & _mode) == _mode) // already visited
            return;

        MetaDataTag tag;
        for (Annotation anno : pkg.getDeclaredAnnotations()) {
            tag = _tags.get(anno.annotationType());
            if (tag == null) {
                handleUnknownPackageAnnotation(pkg, anno);
                continue;
            }

            switch (tag) {
                case NATIVE_QUERIES:
                    if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
                        parseNamedNativeQueries(pkg,
                            ((NamedNativeQueries) anno).value());
                    break;
                case NATIVE_QUERY:
                    if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
                        parseNamedNativeQueries(pkg, (NamedNativeQuery) anno);
                    break;
                case QUERIES:
                    if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
                        parseNamedQueries(pkg, ((NamedQueries) anno).value());
                    break;
                case QUERY:
                    if (isQueryMode() && (pkgMode & MODE_QUERY) == 0)
                        parseNamedQueries(pkg, (NamedQuery) anno);
                    break;
                case STOREDPROCEDURE_QUERIES:
                    if (isQueryMode())
                        parseNamedStoredProcedureQueries(pkg, ((NamedStoredProcedureQueries) anno).value());
                    break;
                case STOREDPROCEDURE_QUERY:
                    if (isQueryMode())
                        parseNamedStoredProcedureQueries(pkg, ((NamedStoredProcedureQuery) anno));
                    break;
                case SEQ_GENERATOR:
                    if (isMappingOverrideMode() &&
                        (pkgMode & MODE_MAPPING) == 0)
                        parseSequenceGenerator(pkg, (SequenceGenerator) anno);
                    break;
                default:
                    throw new UnsupportedException(_loc.get("unsupported", pkg,
                        anno.toString()));
            }
        }

        // always parse mapping stuff after metadata stuff, in case there are
        // dependencies on metadata
        if (isMappingOverrideMode() && (pkgMode & MODE_MAPPING) == 0)
            parsePackageMappingAnnotations(pkg);
    }

    /**
     * Parse package mapping annotations.
     */
    protected void parsePackageMappingAnnotations(Package pkg) {
    }

    /**
     * Allow subclasses to handle unknown annotations.
     */
    protected boolean handleUnknownPackageAnnotation(Package pkg,
        Annotation anno) {
        return false;
    }

    /**
     * The source mode for the given package.
     */
    private int getSourceMode(Package pkg) {
        Number num = _pkgs.get(pkg);
        return (num == null) ? 0 : num.intValue();
    }

    /**
     * Add to the source mode for the given package.
     */
    private void addSourceMode(Package pkg, int mode) {
        Integer num = _pkgs.get(pkg);
        if (num == null)
            num = mode;
        else
            num = num | mode;
        _pkgs.put(pkg, num);
    }

    /**
     * Read annotations for the current type.
     */
    private ClassMetaData parseClassAnnotations() {
        // Check to see if there is cached metadata for the class that we are currently parsing. It
        // is possible that one of the annotations (Entity, Embeddable, MappedSuperclass) is in the
        // orm.xml. We still need to look at these files for other annotations and more importantly
        // setup defaults (ie: Basic fields).
        ClassMetaData m = getRepository().getCachedMetaData(_cls);
        if (m == null) {
            if (!AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls, Entity.class))
                && !AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls, Embeddable.class))
                && !AccessController.doPrivileged(J2DoPrivHelper.isAnnotationPresentAction(_cls,
                    MappedSuperclass.class)))
                return null;
        }
        // find / create metadata
        ClassMetaData meta = (m == null) ? getMetaData() : m;
        if (meta == null)
            return null;

        Entity entity = _cls.getAnnotation(Entity.class);
        MappedSuperclass mapped = _cls.getAnnotation(MappedSuperclass.class);
        Embeddable embeddable = _cls.getAnnotation(Embeddable.class);
        if (isMetaDataMode()) {
            meta.setAbstract(mapped != null);
            if (embeddable != null) meta.setEmbeddable();
            // while the spec only provides for embedded exclusive, it doesn't
            // seem hard to support otherwise
            if (entity == null)
                meta.setEmbeddedOnly(true);
            else {
                meta.setEmbeddedOnly(false);
                if (!StringUtil.isEmpty(entity.name()))
                    meta.setTypeAlias(entity.name());
            }
        }

        // track fetch groups to parse them after fields, since they
        // rely on field metadata
        FetchGroup[] fgs = null;
        DetachedState detached = null;

        // track listeners since we need to merge them with entity callbacks
        Collection<LifecycleCallbacks>[] listeners = null;
        MetaDataTag tag;
        for (Annotation anno : _cls.getDeclaredAnnotations()) {
            tag = _tags.get(anno.annotationType());
            if (tag == null) {
                handleUnknownClassAnnotation(meta, anno);
                continue;
            }

            switch (tag) {
                case ENTITY_LISTENERS:
                    if (isMetaDataMode())
                        listeners = parseEntityListeners(meta,
                            (EntityListeners) anno);
                    break;
                case EXCLUDE_DEFAULT_LISTENERS:
                    if (isMetaDataMode())
                        meta.getLifecycleMetaData()
                            .setIgnoreSystemListeners(true);
                    break;
                case EXCLUDE_SUPERCLASS_LISTENERS:
                    if (isMetaDataMode())
                        meta.getLifecycleMetaData().setIgnoreSuperclassCallbacks
                            (LifecycleMetaData.IGNORE_HIGH);
                    break;
                case FLUSH_MODE:
                    if (isMetaDataMode())
                        warnFlushMode(meta);
                    break;
                case ID_CLASS:
                    if (isMetaDataMode()) {
                    	Class<?> idClass = ((IdClass)anno).value();
                    	if (!Serializable.class.isAssignableFrom(idClass)) {
                    		_log.warn(_loc.get("id-class-not-serializable", idClass, _cls).toString());
                    	}
                        meta.setObjectIdType(((IdClass) anno).value(), true);
                    }
                    break;
                case NATIVE_QUERIES:
                    if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
                        parseNamedNativeQueries(_cls,
                            ((NamedNativeQueries) anno).value());
                    break;
                case NATIVE_QUERY:
                    if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
                        parseNamedNativeQueries(_cls, (NamedNativeQuery) anno);
                    break;
                case QUERIES:
                    if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
                        parseNamedQueries(_cls, ((NamedQueries) anno).value());
                    break;
                case QUERY:
                    if (isQueryMode() && (meta.getSourceMode() & MODE_QUERY)==0)
                        parseNamedQueries(_cls, (NamedQuery) anno);
                    break;
                case STOREDPROCEDURE_QUERIES:
                    if (isQueryMode())
                        parseNamedStoredProcedureQueries(_cls, ((NamedStoredProcedureQueries) anno).value());
                    break;
                case STOREDPROCEDURE_QUERY:
                    if (isQueryMode())
                        parseNamedStoredProcedureQueries(_cls, ((NamedStoredProcedureQuery) anno));
                    break;
                case SEQ_GENERATOR:
                    if (isMappingOverrideMode())
                        parseSequenceGenerator(_cls, (SequenceGenerator) anno);
                    break;
                case DATA_CACHE:
                    if (isMetaDataMode())
                        parseDataCache(meta, (DataCache) anno);
                    break;
                case DATASTORE_ID:
                    if (isMetaDataMode())
                        parseDataStoreId(meta, (DataStoreId) anno);
                    break;
                case DETACHED_STATE:
                    detached = (DetachedState) anno;
                    break;
                case FETCH_GROUP:
                    if (isMetaDataMode())
                        fgs = new FetchGroup[]{ (FetchGroup) anno };
                    break;
                case FETCH_GROUPS:
                    if (isMetaDataMode())
                        fgs = ((FetchGroups) anno).value();
                    break;
                case MANAGED_INTERFACE:
                    if (isMetaDataMode())
                        parseManagedInterface(meta, (ManagedInterface) anno);
                    break;
                case ACCESS:
                    if (isMetaDataMode())
                        parseAccess(meta, (Access)anno);
                    break;
                case CACHEABLE:
                    if (isMetaDataMode()) {
                        parseCache(meta, (Cacheable) anno);
                    }
                    break;
                default:
                    throw new UnsupportedException(_loc.get("unsupported", _cls,
                        anno.toString()));
            }
        }

        if (isMetaDataMode()) {
            parseDetachedState(meta, detached);

            // merge callback methods with declared listeners
            int[] highs = null;
            if (listeners != null) {
                highs = new int[listeners.length];
                for (int i = 0; i < listeners.length; i++)
                    if (listeners[i] != null)
                        highs[i] = listeners[i].size();
            }
            recordCallbacks(meta, parseCallbackMethods(_cls, listeners, false,
                false, getRepository()), highs, false);

            // scan possibly non-PC hierarchy for callbacks.
            // redundant for PC superclass but we don't know that yet
            // so let LifecycleMetaData determine that
            if (_cls.getSuperclass() != null &&
                !Object.class.equals(_cls.getSuperclass())) {
                recordCallbacks(meta, parseCallbackMethods(_cls.getSuperclass(),
                    null, true, false, getRepository()), null, true);
            }
        }

        for (FieldMetaData fmd : meta.getDeclaredFields())
            if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
                parseMemberAnnotations(fmd);
        // parse fetch groups after fields
        if (fgs != null)
            parseFetchGroups(meta, fgs);

        // always parse mapping after metadata in case there are dependencies
        if (isMappingOverrideMode()) {
            parseClassMappingAnnotations(meta);
            for (FieldMetaData fmd : meta.getDeclaredFields())
                if (fmd.getManagement() == FieldMetaData.MANAGE_PERSISTENT)
                    parseMemberMappingAnnotations(fmd);
        }
        return meta;
    }

    /**
     * Set the explicit access type, if specified.
     */
    private void parseAccess(ClassMetaData meta, Access access) {
    	if (access != null) {
    		meta.setAccessType(AccessCode.EXPLICIT
            | (access.value() == AccessType.FIELD ?
            	AccessCode.FIELD : AccessCode.PROPERTY));
    	}
    }

    /**
     * Parse class mapping annotations.
     */
    protected void parseClassMappingAnnotations(ClassMetaData meta) {
    }

    /**
     * Allow subclasses to handle unknown annotations.
     */
    protected boolean handleUnknownClassAnnotation(ClassMetaData meta,
        Annotation anno) {
        return false;
    }

    /**
     * Find or create metadata for the given type. May return null if
     * this class has already been parsed fully.
     */
    private ClassMetaData getMetaData() {
        ClassMetaData meta = getRepository().getCachedMetaData(_cls);
        if (meta != null
            && ((isMetaDataMode()
                && (meta.getSourceMode() & MODE_META) != 0)
                || (isMappingMode() && (meta.getSourceMode() & MODE_MAPPING) != 0) ) ) {
            if (_log.isWarnEnabled()) {
                _log.warn(_loc.get("dup-metadata", _cls.getName()));
            }
            if(_log.isTraceEnabled()) {
                _log.trace(String.format(
                    "MetaData originally obtained from file: %s under mode :%d with scope %s, and type :%d",
                    meta.getSourceName(), meta.getSourceMode(), meta.getSourceScope(), meta.getSourceType()));
            }
            return null;
        }

        if (meta == null) {
            meta = getRepository().addMetaData(_cls, getAccessCode(_cls));
            meta.setEnvClassLoader(_envLoader);
            meta.setSourceMode(MODE_NONE);
            meta.setSource(getSourceFile(), SourceTracker.SRC_ANNOTATIONS, getSourceFile() == null ? ""
                : getSourceFile().getPath());
        }
        return meta;
    }

    /**
     * Gets the explicit access for the class, if any.
     * Explicit access type specification does not affect the access type of
     * other entity classes or mapped super classes in the entity hierarchy.
     */
    private int getAccessCode(Class<?> cls) {
        int accessCode = AccessCode.UNKNOWN;
        Access access = AccessController.doPrivileged(
            J2DoPrivHelper.getAnnotationAction(cls, Access.class));
        if (access != null) {
            accessCode |=  AccessCode.EXPLICIT |
                (access.value() == AccessType.FIELD ?
                AccessCode.FIELD : AccessCode.PROPERTY);
        }
        return accessCode;
    }

    /**
     * Determine the source file we're parsing.
     */
    protected File getSourceFile() {
        if (_file != null)
            return _file;

        Class<?> cls = _cls;
        while (cls.getEnclosingClass() != null)
            cls = cls.getEnclosingClass();

        String rsrc = StringUtil.replace(cls.getName(), ".", "/");
        ClassLoader loader = AccessController.doPrivileged(
            J2DoPrivHelper.getClassLoaderAction(cls));
        if (loader == null)
            loader = AccessController.doPrivileged(
                J2DoPrivHelper.getSystemClassLoaderAction());
        if (loader == null)
            return null;
        URL url = AccessController.doPrivileged(
            J2DoPrivHelper.getResourceAction(loader, rsrc + ".java"));
        if (url == null) {
            url = AccessController.doPrivileged(
                J2DoPrivHelper.getResourceAction(loader, rsrc + ".class"));
            if (url == null)
                return null;
        }
        try {
            _file = new File(url.toURI());
        } catch (URISyntaxException e) {
        } catch (IllegalArgumentException iae) {
            // this is thrown when the URI is non-hierarchical (aka JBoss)
        }
        return _file;
    }

    /**
     * Parse @DataStoreId.
     */
    private void parseDataStoreId(ClassMetaData meta, DataStoreId id) {
        parseDataStoreId(meta, id.strategy(), id.generator());
    }

    static void parseDataStoreId(ClassMetaData meta, GenerationType strategy,
        String generator) {
        meta.setIdentityType(ClassMetaData.ID_DATASTORE);

        int strat = getGeneratedValueStrategy(meta, strategy,
            generator);
        if (strat != -1)
            meta.setIdentityStrategy(strat);
        else {
            switch (strategy) {
                case TABLE:
                case SEQUENCE:
                    // technically we should have separate system table and
                    // sequence generators, but it's easier to just rely on
                    // the system org.apache.openjpa.Sequence setting for both
                    if (StringUtil.isEmpty(generator))
                        meta.setIdentitySequenceName(
                            SequenceMetaData.NAME_SYSTEM);
                    else
                        meta.setIdentitySequenceName(generator);
                    break;
                case AUTO:
                    meta.setIdentityStrategy(ValueStrategies.NATIVE);
                    break;
                case IDENTITY:
                    meta.setIdentityStrategy(ValueStrategies.AUTOASSIGN);
                    break;
                default:
                    throw new UnsupportedException(strategy.toString());
            }
        }
    }

    /**
     * Warn that @FlushMode is not supported.
     */
    private void warnFlushMode(Object context) {
        if (_log.isWarnEnabled())
            _log.warn(_loc.get("unsupported", "FlushMode", context));
    }

    /**
     * Parse @DataCache.
     *
     */
    private void parseDataCache(ClassMetaData meta, DataCache cache) {
        parseDataCache(meta, cache.enabled(), cache.name(), cache.timeout());
    }

    static void parseDataCache(ClassMetaData meta,
            boolean enabled,
            String name,
            int timeout) {
        if (timeout != Integer.MIN_VALUE) {
            meta.setDataCacheTimeout(timeout);
        }
        String cacheName = name;
        if (StringUtil.isEmpty(cacheName)) {
            cacheName = org.apache.openjpa.datacache.DataCache.NAME_DEFAULT;
        }
        meta.setDataCacheName(enabled ? cacheName : null);
    }

    private void parseManagedInterface(ClassMetaData meta,
        ManagedInterface iface) {
        meta.setManagedInterface(true);
    }

    /**
     * Parse @DetachedState. The annotation may be null.
     */
    private void parseDetachedState(ClassMetaData meta,
        DetachedState detached) {
        if (detached != null) {
            if (!detached.enabled())
                meta.setDetachedState(null);
            else if (StringUtil.isEmpty(detached.fieldName()))
                meta.setDetachedState(ClassMetaData.SYNTHETIC);
            else
                meta.setDetachedState(detached.fieldName());
        } else {
            Field[] fields = (Field[]) AccessController.doPrivileged(
                J2DoPrivHelper.getDeclaredFieldsAction(
                    meta.getDescribedType()));
            for (Field field : fields)
                if (AccessController.doPrivileged(J2DoPrivHelper
                        .isAnnotationPresentAction(field, DetachedState.class)))
                    meta.setDetachedState(field.getName());
        }
    }

    /**
     * Parse @EntityListeners
     */
    private Collection<LifecycleCallbacks>[] parseEntityListeners
        (ClassMetaData meta, EntityListeners listeners) {
        Class<?>[] classes = listeners.value();
        Collection<Class<?>> listenerColl = null;
        Collection<LifecycleCallbacks>[] parsed = null;
        for (Class<?> cls : classes) {
            if (!_conf.getCallbackOptionsInstance().getAllowsDuplicateListener()) {
                if (listenerColl == null)
                    listenerColl = new ArrayList<>();
                if (listenerColl.contains(cls))
                    continue;
                listenerColl.add(cls);
            }

            parsed = parseCallbackMethods(cls, parsed, true, true,
                getRepository());
        }
        return parsed;
    }

    /**
     * Parse callback methods into the given array, and return that array,
     * creating one if null. Each index into the array is a collection of
     * callback adapters for that numeric event type.
     *
     * @param sups whether to scan superclasses
     * @param listener whether this is a listener or not
     */
    public static Collection<LifecycleCallbacks>[] parseCallbackMethods
        (Class<?> cls, Collection<LifecycleCallbacks>[] callbacks, boolean sups,
        boolean listener, MetaDataRepository repos) {

        if (cls == null)
            throw new IllegalArgumentException("cls cannot be null");

        // first sort / filter based on inheritance
        Set<Method> methods = new TreeSet<>(MethodComparator.
            getInstance());

        int mods;
        Class<?> sup = cls;
        MethodKey key;
        Set<MethodKey> seen = new HashSet<>();
        do {
            for (Method m : (Method[]) AccessController.doPrivileged(J2DoPrivHelper.getDeclaredMethodsAction(sup))) {
                mods = m.getModifiers();
                if (Modifier.isStatic(mods) || Modifier.isFinal(mods) ||
                    Object.class.equals(m.getDeclaringClass()))
                    continue;

                key = new MethodKey(m);
                if (!seen.contains(key)) {
                    methods.add(m);
                    seen.add(key);
                }
            }
            sup = sup.getSuperclass();
        } while (sups && !Object.class.equals(sup));

        OpenJPAConfiguration conf = repos.getConfiguration();
        for (Method m : methods) {
            for (Annotation anno : (Annotation[]) AccessController
                .doPrivileged(J2DoPrivHelper
                    .getDeclaredAnnotationsAction(m))) {
                MetaDataTag tag = _tags.get(anno.annotationType());
                if (tag == null)
                    continue;
                int[] events = MetaDataParsers.getEventTypes(tag, conf);
                if (events == null)
                    continue;

                if (callbacks == null)
                    callbacks = (Collection<LifecycleCallbacks>[])
                        new Collection[LifecycleEvent.ALL_EVENTS.length];

                for (int e : events) {
                    if (callbacks[e] == null)
                        callbacks[e] = new ArrayList<>(3);
                    MetaDataParsers.validateMethodsForSameCallback(cls,
                            callbacks[e], m, tag, conf, repos.getLog());
                    if (listener) {
                        callbacks[e].add(new BeanLifecycleCallbacks(cls, m,
                                false));
                    }
                    else {
                        callbacks[e].add(new MethodLifecycleCallbacks(m,
                                false));
                    }
                }
            }
        }
        return callbacks;
    }

    /**
     * Store lifecycle metadata.
     */
    private void recordCallbacks(ClassMetaData cls,
        Collection<LifecycleCallbacks>[] callbacks, int[] highs,
        boolean superClass) {
        if (callbacks == null)
            return;
        LifecycleMetaData meta = cls.getLifecycleMetaData();
        LifecycleCallbacks[] array;
        for (int event : LifecycleEvent.ALL_EVENTS) {
            if (callbacks[event] == null)
                continue;
            array = callbacks[event].toArray
                (new LifecycleCallbacks[callbacks[event].size()]);

            if (superClass) {
                meta.setNonPCSuperclassCallbacks(event, array,
                    (highs == null) ? 0 : highs[event]);
            } else {
                meta.setDeclaredCallbacks(event, array,
                    (highs == null) ? 0 : highs[event]);
            }
        }
    }

    /**
     * Create fetch groups.
     * If FetchGroup A includes FetchGroup B, then a bi-link is set between
     * A and B. Both A and B must be declared in the same Class.
     * <br>
     * Call {@link #parseFetchAttribute(ClassMetaData, org.apache.openjpa.meta.FetchGroup, FetchAttributeImpl)}
     * only after the
     * bi-links have been established, because a field f will not only add the
     * fetch group A which explicitly includes f to its custom fetch groups but
     * also will also add any fetch group B that includes A.
     */
    static void parseFetchGroups(ClassMetaData meta, FetchGroup... groups) {
       FetchGroupImpl[] fetchGroupImpls = new FetchGroupImpl[groups.length];
       for (int i = 0; i < groups.length; i++) {
           FetchAttribute[] fetchAttributes = groups[i].attributes();
           FetchAttributeImpl[] fetchAttributeImpls= null;
           if (fetchAttributes != null && fetchAttributes.length > 0) {
               fetchAttributeImpls = new FetchAttributeImpl[fetchAttributes.length];
               for (int j = 0; j < fetchAttributes.length; j++) {
                   fetchAttributeImpls[j] =
                           new FetchAttributeImpl(fetchAttributes[j].name(), fetchAttributes[j].recursionDepth());
               }
           }
           fetchGroupImpls[i] = new FetchGroupImpl(groups[i].name(), groups[i].postLoad());
           if (fetchAttributeImpls != null) {
               fetchGroupImpls[i].setAttributes(fetchAttributeImpls);
           }
           if (groups[i].fetchGroups() != null) {
               fetchGroupImpls[i].setFetchGroups(groups[i].fetchGroups());
           }
       }

       parseFetchGroups(meta, fetchGroupImpls);
    }

   /**
    * Parse fetch group input for the FetchGroup and FetchGroups annotations
    * as well as for the fetch-group and fetch-groups XML metadata
    * @param meta
    * @param groups
    */
   static void parseFetchGroups(ClassMetaData meta, FetchGroupImpl... groups) {
       org.apache.openjpa.meta.FetchGroup fg;
       for (FetchGroupImpl group : groups) {
           if (StringUtil.isEmpty(group.name()))
               throw new MetaDataException(_loc.get("unnamed-fg", meta));

           fg = meta.addDeclaredFetchGroup(group.name());
           if (group.postLoad())
               fg.setPostLoad(true);
           for (String s : group.fetchGroups()) {
               fg.addDeclaredInclude(s);
           }
       }
       // Add the parent-child style bi-links between fetch groups in a
       // separate pass.
       for (FetchGroupImpl group:groups) {
           fg = meta.getFetchGroup(group.name());
           String[] includedFetchGropNames = fg.getDeclaredIncludes();
           for (String includedFectchGroupName:includedFetchGropNames) {
               org.apache.openjpa.meta.FetchGroup child =
               meta.getFetchGroup(includedFectchGroupName);
               if (child == null)
                   throw new UserException(_loc.get("missing-included-fg",
                           meta.getDescribedType().getName(), fg.getName(),
                           includedFectchGroupName));
               child.addContainedBy(fg);
           }
       }

       for (FetchGroupImpl group : groups) {
           fg = meta.getFetchGroup(group.name());
           for (FetchAttributeImpl attr : group.attributes())
               parseFetchAttribute(meta, fg, attr);
       }
   }


    /**
     * Set a field's fetch group.
     */
    private static void parseFetchAttribute(ClassMetaData meta,
        org.apache.openjpa.meta.FetchGroup fg, FetchAttributeImpl attr) {
        FieldMetaData field = meta.getDeclaredField(attr.name());
        if (field == null
            || field.getManagement() != FieldMetaData.MANAGE_PERSISTENT)
            throw new MetaDataException(_loc.get("bad-fg-field", fg.getName(),
                meta, attr.name()));

        field.setInFetchGroup(fg.getName(), true);
        Set<String> parentFetchGroups = fg.getContainedBy();
        for (Object parentFetchGroup : parentFetchGroups)
        	field.setInFetchGroup(parentFetchGroup.toString(), true);
        if (attr.recursionDepth() != Integer.MIN_VALUE)
            fg.setRecursionDepth(field, attr.recursionDepth());
    }

    /**
     * Read annotations for the given member.
     */
    private void parseMemberAnnotations(FieldMetaData fmd) {
        // look for persistence strategy in annotation table
        Member member = getRepository().getMetaDataFactory().getDefaults().
            getBackingMember(fmd);
        PersistenceStrategy pstrat = PersistenceMetaDataDefaults.
            getPersistenceStrategy(fmd, member);
        if (pstrat == null)
            return;
        fmd.setExplicit(true);

        AnnotatedElement el = (AnnotatedElement) member;
        boolean lob = AccessController.doPrivileged(J2DoPrivHelper
                .isAnnotationPresentAction(el, Lob.class));
        if (isMetaDataMode()) {
            switch (pstrat) {
                case BASIC:
                    parseBasic(fmd, (Basic) el.getAnnotation(Basic.class), lob);
                    break;
                case MANY_ONE:
                    parseManyToOne(fmd, (ManyToOne) el.getAnnotation
                        (ManyToOne.class));
                    break;
                case ONE_ONE:
                    parseOneToOne(fmd, (OneToOne) el.getAnnotation
                        (OneToOne.class));
                    break;
                case EMBEDDED:
                    parseEmbedded(fmd, (Embedded) el.getAnnotation
                        (Embedded.class));
                    break;
                case ONE_MANY:
                    parseOneToMany(fmd, (OneToMany) el.getAnnotation
                        (OneToMany.class));
                    break;
                case MANY_MANY:
                    parseManyToMany(fmd, (ManyToMany) el.getAnnotation
                        (ManyToMany.class));
                    break;
                case PERS:
                    parsePersistent(fmd, (Persistent) el.getAnnotation
                        (Persistent.class));
                    break;
                case PERS_COLL:
                    parsePersistentCollection(fmd, (PersistentCollection)
                        el.getAnnotation(PersistentCollection.class));
                    break;
                case ELEM_COLL:
                    parseElementCollection(fmd, (ElementCollection)
                        el.getAnnotation(ElementCollection.class));
                    break;
                case PERS_MAP:
                    parsePersistentMap(fmd, (PersistentMap)
                        el.getAnnotation(PersistentMap.class));
                    break;
                case TRANSIENT:
                    break;
                default:
                    throw new InternalException();
            }
        }

        if (isMappingOverrideMode() && lob)
            parseLobMapping(fmd);

        // extensions
        MetaDataTag tag;
        for (Annotation anno : el.getDeclaredAnnotations()) {
            tag = _tags.get(anno.annotationType());
            if (tag == null) {
                handleUnknownMemberAnnotation(fmd, anno);
                continue;
            }

            switch (tag) {
                case ACCESS:
                    parseAccess(fmd, (Access)anno);
                    break;
                case FLUSH_MODE:
                    if (isMetaDataMode())
                        warnFlushMode(fmd);
                    break;
                case GENERATED_VALUE:
                    if (isMappingOverrideMode())
                        parseGeneratedValue(fmd, (GeneratedValue) anno);
                    break;
                case ID:
                case EMBEDDED_ID:
                    fmd.setPrimaryKey(true);
                    break;
                case MAPPED_BY_ID:
                    parseMapsId(fmd, (MapsId)anno);
                    break;
                case MAP_KEY:
                    if (isMappingOverrideMode())
                        parseMapKey(fmd, (MapKey) anno);
                    break;
                case MAP_KEY_CLASS:
                    if (isMappingOverrideMode())
                        parseMapKeyClass(fmd, (MapKeyClass) anno);
                    break;
                case ORDER_BY:
                    parseOrderBy(fmd,
                        (OrderBy) el.getAnnotation(OrderBy.class));
                    break;
                case SEQ_GENERATOR:
                    if (isMappingOverrideMode())
                        parseSequenceGenerator(el, (SequenceGenerator) anno);
                    break;
                case VERSION:
                    fmd.setVersion(true);
                    break;
                case DEPENDENT:
                    if (isMetaDataMode() && ((Dependent) anno).value())
                        fmd.setCascadeDelete(ValueMetaData.CASCADE_AUTO);
                    break;
                case ELEM_DEPENDENT:
                    if (isMetaDataMode() && ((ElementDependent) anno).value())
                        fmd.getElement().setCascadeDelete
                            (ValueMetaData.CASCADE_AUTO);
                    break;
                case ELEM_TYPE:
                    if (isMetaDataMode())
                        fmd.getElement().setTypeOverride(toOverrideType
                            (((ElementType) anno).value()));
                    break;
                case EXTERNAL_VALS:
                    if (isMetaDataMode())
                        fmd.setExternalValues(StringUtil.join(((ExternalValues) anno).value(), ","));
                    break;
                case EXTERNALIZER:
                    if (isMetaDataMode())
                        fmd.setExternalizer(((Externalizer) anno).value());
                    break;
                case FACTORY:
                    if (isMetaDataMode())
                        fmd.setFactory(((Factory) anno).value());
                    break;
                case INVERSE_LOGICAL:
                    if (isMetaDataMode())
                        fmd.setInverse(((InverseLogical) anno).value());
                    break;
                case KEY_DEPENDENT:
                    if (isMetaDataMode() && ((KeyDependent) anno).value())
                        fmd.getKey()
                            .setCascadeDelete(ValueMetaData.CASCADE_AUTO);
                    break;
                case KEY_TYPE:
                    if (isMetaDataMode())
                        fmd.getKey().setTypeOverride(toOverrideType(((KeyType)
                            anno).value()));
                    break;
                case LOAD_FETCH_GROUP:
                	if (isMetaDataMode())
                        fmd.setLoadFetchGroup(((LoadFetchGroup) anno).value());
                	break;
                case LRS:
                    if (isMetaDataMode())
                        fmd.setLRS(((LRS) anno).value());
                    break;
                case READ_ONLY:
                    if (isMetaDataMode())
                        parseReadOnly(fmd, (ReadOnly) anno);
                    break;
                case TYPE:
                    if (isMetaDataMode())
                        fmd.setTypeOverride(toOverrideType(((Type) anno).
                            value()));
                    break;
                case CONVERT:
                    if (isMetaDataMode() && !((Convert) anno).disableConversion())
                        fmd.setConverter(((Convert) anno).converter());
                    break;
                default:
                    throw new UnsupportedException(_loc.get("unsupported", fmd,
                        anno.toString()));
            }
        }
    }

    /**
     * Parse member mapping components.
     */
    protected void parseMemberMappingAnnotations(FieldMetaData fmd) {
    }

    /**
     * Parse @Cache.
     */
    private void parseCache(ClassMetaData meta, Cacheable cacheable) {
        meta.setCacheEnabled(cacheable.value());
    }

    /**
     * Allow subclasses to handle unknown annotations.
     */
    protected boolean handleUnknownMemberAnnotation(FieldMetaData fmd,
        Annotation anno) {
        return false;
    }

    /**
     * Convert the given class to its OpenJPA type override equivalent.
     */
    public static Class<?> toOverrideType(Class<?> cls) {
        return (cls == Entity.class)
            ? org.apache.openjpa.enhance.PersistenceCapable.class : cls;
    }

    /**
     * Parse @ReadOnly.
     */
    private void parseReadOnly(FieldMetaData fmd, ReadOnly ro) {
        if (ro.value() == UpdateAction.RESTRICT)
            fmd.setUpdateStrategy(UpdateStrategies.RESTRICT);
        else if (ro.value() == UpdateAction.IGNORE)
            fmd.setUpdateStrategy(UpdateStrategies.IGNORE);
        else
            throw new InternalException();
    }

    /**
     * Sets value generation information for the given field.
     */
    private void parseGeneratedValue(FieldMetaData fmd, GeneratedValue gen) {
        GenerationType strategy = gen.strategy();
        String generator = gen.generator();
        parseGeneratedValue(fmd, strategy, generator);
    }

    /**
     * Sets value generation information for the given field.
     */
    static void parseGeneratedValue(FieldMetaData fmd, GenerationType strategy,
        String generator) {
        int strat = getGeneratedValueStrategy(fmd, strategy, generator);
        if (strat != -1)
            fmd.setValueStrategy(strat);
        else {
            switch (strategy) {
                case TABLE:
                case SEQUENCE:
                    // technically we should have separate system table and
                    // sequence generators, but it's easier to just rely on
                    // the system org.apache.openjpa.Sequence setting for both
                    if (StringUtil.isEmpty(generator))
                        fmd.setValueSequenceName(SequenceMetaData.NAME_SYSTEM);
                    else
                        fmd.setValueSequenceName(generator);
                    break;
                case AUTO:
                    fmd.setValueSequenceName(SequenceMetaData.NAME_SYSTEM);
                    break;
                case IDENTITY:
                    fmd.setValueStrategy(ValueStrategies.AUTOASSIGN);
                    break;
                default:
                    throw new UnsupportedException(strategy.toString());
            }
        }
    }

    /**
     * Return the value strategy for the given generator, or -1 if the
     * strategy depends on the <code>GenerationType</code> rather than the
     * generator name.
     */
    private static int getGeneratedValueStrategy(Object context,
        GenerationType strategy, String generator) {
        if (strategy != AUTO || StringUtil.isEmpty(generator))
            return -1;

        if (Generator.UUID_HEX.equals(generator))
            return ValueStrategies.UUID_HEX;
        if (Generator.UUID_STRING.equals(generator))
            return ValueStrategies.UUID_STRING;
        if (Generator.UUID_TYPE4_HEX.equals(generator))
            return ValueStrategies.UUID_TYPE4_HEX;
        if (Generator.UUID_TYPE4_STRING.equals(generator))
            return ValueStrategies.UUID_TYPE4_STRING;
        throw new MetaDataException(_loc.get("generator-bad-strategy",
            context, generator));
    }

    /**
     * Parse @Basic. Given annotation may be null.
     */
    private void parseBasic(FieldMetaData fmd, Basic anno, boolean lob) {
        Class<?> type = fmd.getDeclaredType();
        if (lob && type != String.class
            && type != char[].class && type != Character[].class
            && type != byte[].class && type != Byte[].class)
            fmd.setSerialized(true);
        else if (!lob) {
            switch (fmd.getDeclaredTypeCode()) {
                case JavaTypes.OBJECT:
                    if (Enum.class.isAssignableFrom(type))
                        break;
                    // else no break
                case JavaTypes.COLLECTION:
                case JavaTypes.MAP:
                case JavaTypes.PC:
                case JavaTypes.PC_UNTYPED:
                    if (Serializable.class.isAssignableFrom(type))
                        fmd.setSerialized(true);
                    else
                        throw new MetaDataException(_loc.get("bad-meta-anno",
                            fmd, "Basic"));
                    break;
                case JavaTypes.ARRAY:
                    if (type == char[].class || type == Character[].class
                        || type == byte[].class || type == Byte[].class)
                        break;
                    if (Serializable.class.isAssignableFrom
                        (type.getComponentType()))
                        fmd.setSerialized(true);
                    else
                        throw new MetaDataException(_loc.get("bad-meta-anno",
                            fmd, "Basic"));
                    break;
            }
        }

        if (anno == null)
            return;
        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (!anno.optional())
            fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
    }

    /**
     * Parse @ManyToOne.
     */
    private void parseManyToOne(FieldMetaData fmd, ManyToOne anno) {
        if (!JavaTypes.maybePC(fmd.getValue()))
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "ManyToOne"));

        // don't specifically exclude relation from DFG b/c that will prevent
        // us from even reading the fk when reading from the primary table,
        // which is not what most users will want
        if (anno.fetch() == FetchType.EAGER)
            fmd.setInDefaultFetchGroup(true);
        if (!anno.optional())
            fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
        if (anno.targetEntity() != void.class)
            fmd.setTypeOverride(anno.targetEntity());
        setCascades(fmd, anno.cascade());
        fmd.setAssociationType(FieldMetaData.MANY_TO_ONE);
    }

    /**
     * Parse @OneToOne.
     */
    private void parseOneToOne(FieldMetaData fmd, OneToOne anno) {
        if (!JavaTypes.maybePC(fmd.getValue()))
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "OneToOne"));

        // don't specifically exclude relation from DFG b/c that will prevent
        // us from even reading the fk when reading from the primary table,
        // which is not what most users will want
        if (anno.fetch() == FetchType.EAGER)
            fmd.setInDefaultFetchGroup(true);
        if (!anno.optional())
            fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);

        if (isMappingOverrideMode() && !StringUtil.isEmpty(anno.mappedBy()))
            fmd.setMappedBy(anno.mappedBy());
        if (anno.targetEntity() != void.class)
            fmd.setTypeOverride(anno.targetEntity());
        setCascades(fmd, anno.cascade());
        setOrphanRemoval(fmd, anno.orphanRemoval());
        fmd.setAssociationType(FieldMetaData.ONE_TO_ONE);
    }

    /**
     * Parse @Embedded. Given annotation may be null.
     */
    private void parseEmbedded(FieldMetaData fmd, Embedded anno) {
        if (!JavaTypes.maybePC(fmd.getValue()))
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "Embedded"));

        fmd.setInDefaultFetchGroup(true);
        fmd.setEmbedded(true);

        if (fmd.getEmbeddedMetaData() == null)
            fmd.addEmbeddedMetaData(getAccessCode(fmd.getDeclaredType()));
    }

    /**
     * Parse @OneToMany.
     */
    private void parseOneToMany(FieldMetaData fmd, OneToMany anno) {
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.ARRAY:
            case JavaTypes.COLLECTION:
            case JavaTypes.MAP:
                if (JavaTypes.maybePC(fmd.getElement()))
                    break;
                // no break
            default:
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "OneToMany"));
        }

        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (isMappingOverrideMode() && !StringUtil.isEmpty(anno.mappedBy()))
            fmd.setMappedBy(anno.mappedBy());
        if (anno.targetEntity() != void.class)
            fmd.getElement().setDeclaredType(anno.targetEntity());
        setCascades(fmd.getElement(), anno.cascade());
        setOrphanRemoval(fmd.getElement(), anno.orphanRemoval());
        fmd.setAssociationType(FieldMetaData.ONE_TO_MANY);
    }

    /**
     * Parse @ManyToMany.
     */
    private void parseManyToMany(FieldMetaData fmd, ManyToMany anno) {
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.ARRAY:
            case JavaTypes.COLLECTION:
            case JavaTypes.MAP:
                if (fmd.getDeclaredType() == Properties.class || JavaTypes.maybePC(fmd.getElement()))
                    break;
                // no break
            default:
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "ManyToMany"));
        }

        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (isMappingOverrideMode() && !StringUtil.isEmpty(anno.mappedBy()))
            fmd.setMappedBy(anno.mappedBy());
        if (anno.targetEntity() != void.class)
            fmd.getElement().setDeclaredType(anno.targetEntity());
        setCascades(fmd.getElement(), anno.cascade());
        fmd.setAssociationType(FieldMetaData.MANY_TO_MANY);
    }

    /**
     * Parse @MapKey.
     */
    private void parseMapKey(FieldMetaData fmd, MapKey anno) {
        String name = anno.name();
        if (StringUtil.isEmpty(name))
            fmd.getKey().setValueMappedBy(ValueMetaData.MAPPED_BY_PK);
        else
            fmd.getKey().setValueMappedBy(name);
    }

    /**
     * Parse @MapKeyClass.
     */
    private void parseMapKeyClass(FieldMetaData fmd, MapKeyClass anno) {
        if (anno.value() != void.class)
            fmd.getKey().setDeclaredType(anno.value());
        else
            throw new IllegalArgumentException(
                 "The value of the MapClassClass cannot be null");
    }

    /**
     * Parse @MapsId.
     */
    private void parseMapsId(FieldMetaData fmd, MapsId anno) {
        String value = anno.value();
        if (value != null)
            fmd.setMappedByIdValue(value);
        else
            fmd.setMappedByIdValue("");
    }

    /**
     * Setup the field as a LOB mapping.
     */
    protected void parseLobMapping(FieldMetaData fmd) {
    }

    /**
     * Parse @OrderBy.
     */
    private void parseOrderBy(FieldMetaData fmd, OrderBy anno) {
        String dec = anno.value();
        if (fmd.isElementCollection() &&
            fmd.getElement().getEmbeddedMetaData() != null) {
                if (dec.length() == 0 || dec.equals("ASC") ||
                    dec.equals("DESC"))
                    throw new MetaDataException(_loc.get(
                        "invalid-orderBy", fmd));
        }
        if (dec.length() == 0 || dec.equals("ASC"))
            dec = Order.ELEMENT + " asc";
        else if (dec.equals("DESC"))
            dec = Order.ELEMENT + " desc";

        fmd.setOrderDeclaration(dec);
    }

    /**
     * Parse @Persistent.
     */
    private void parsePersistent(FieldMetaData fmd, Persistent anno) {
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.ARRAY:
                if (fmd.getDeclaredType() == byte[].class
                    || fmd.getDeclaredType() == Byte[].class
                    || fmd.getDeclaredType() == char[].class
                    || fmd.getDeclaredType() == Character[].class)
                    break;
                // no break
            case JavaTypes.COLLECTION:
            case JavaTypes.MAP:
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "Persistent"));
        }

        if (!StringUtil.isEmpty(anno.mappedBy()))
            fmd.setMappedBy(anno.mappedBy());
        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (!anno.optional())
            fmd.setNullValue(FieldMetaData.NULL_EXCEPTION);
        setCascades(fmd, anno.cascade());
        if (anno.embedded()) {
            if (!JavaTypes.maybePC(fmd.getValue()))
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "Persistent(embedded=true)"));
            fmd.setEmbedded(true);
            if (fmd.getEmbeddedMetaData() == null) {
                fmd.addEmbeddedMetaData(getAccessCode(fmd.getDeclaredType()));
            }
        }
    }

    /**
     * Parse @PersistentCollection.
     */
    private void parsePersistentCollection(FieldMetaData fmd,
        PersistentCollection anno) {
        if (fmd.getDeclaredTypeCode() != JavaTypes.ARRAY
            && fmd.getDeclaredTypeCode() != JavaTypes.COLLECTION)
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "PersistentCollection"));

        fmd.setPersistentCollection(true);

        if (!StringUtil.isEmpty(anno.mappedBy()))
            fmd.setMappedBy(anno.mappedBy());
        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (anno.elementType() != void.class)
            fmd.getElement().setDeclaredType(anno.elementType());
        setCascades(fmd.getElement(), anno.elementCascade());
        if (anno.elementEmbedded()) {
            if (!JavaTypes.maybePC(fmd.getElement()))
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "PersistentCollection(embeddedElement=true)"));
            fmd.getElement().setEmbedded(true);
            if (fmd.getElement().getEmbeddedMetaData() == null) {
                fmd.getElement().addEmbeddedMetaData(
                    getAccessCode(fmd.getElement().getDeclaredType()));
            }
        }
    }

    /**
     * Parse @ElementCollection.
     */
    private void parseElementCollection(FieldMetaData fmd,
        ElementCollection anno) {
        // TODO: throw exception if the runtime env is OpenJpa 1.x

        if (fmd.getDeclaredTypeCode() != JavaTypes.COLLECTION &&
            fmd.getDeclaredTypeCode() != JavaTypes.MAP)
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "ElementCollection"));

        if (anno.targetClass() != void.class)
            fmd.getElement().setDeclaredType(anno.targetClass());
        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        fmd.setElementCollection(true);
        ValueMetaData elem = fmd.getElement();
        boolean isEnum = elem.getDeclaredType().isEnum();
        if (!isEnum && JavaTypes.maybePC(elem)) {
            elem.setEmbedded(true);
            if (elem.getEmbeddedMetaData() == null)
                elem.addEmbeddedMetaData(getAccessCode(elem.getDeclaredType()));
        }
    }

    /**
     * Parse @PersistentMap.
     */
    private void parsePersistentMap(FieldMetaData fmd, PersistentMap anno) {
        if (fmd.getDeclaredTypeCode() != JavaTypes.MAP)
            throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                "PersistentMap"));

        fmd.setInDefaultFetchGroup(anno.fetch() == FetchType.EAGER);
        if (anno.keyType() != void.class)
            fmd.getKey().setDeclaredType(anno.keyType());
        if (anno.elementType() != void.class)
            fmd.getElement().setDeclaredType(anno.elementType());
        setCascades(fmd.getKey(), anno.keyCascade());
        setCascades(fmd.getElement(), anno.elementCascade());
        if (anno.keyEmbedded()) {
            if (!JavaTypes.maybePC(fmd.getKey()))
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "PersistentMap(embeddedKey=true)"));
            fmd.getKey().setEmbedded(true);
            if (fmd.getKey().getEmbeddedMetaData() == null) {
                fmd.getKey().addEmbeddedMetaData(
                    getAccessCode(fmd.getKey().getDeclaredType()));
            }
        }
        if (anno.elementEmbedded()) {
            if (!JavaTypes.maybePC(fmd.getElement()))
                throw new MetaDataException(_loc.get("bad-meta-anno", fmd,
                    "PersistentMap(embeddedValue=true)"));
            fmd.getElement().setEmbedded(true);
            if (fmd.getElement().getEmbeddedMetaData() == null)
                fmd.getElement().addEmbeddedMetaData(
                    getAccessCode(fmd.getElement().getDeclaredType()));
        }
    }

    /**
     * Set cascades on relation.
     */
    private void setCascades(ValueMetaData vmd, CascadeType[] cascades) {
        for (CascadeType cascade : cascades) {
            if (cascade == CascadeType.ALL || cascade == CascadeType.REMOVE)
                vmd.setCascadeDelete(ValueMetaData.CASCADE_IMMEDIATE);
            if (cascade == CascadeType.ALL || cascade == CascadeType.PERSIST)
                vmd.setCascadePersist(ValueMetaData.CASCADE_IMMEDIATE, false);
            if (cascade == CascadeType.ALL || cascade == CascadeType.MERGE)
                vmd.setCascadeAttach(ValueMetaData.CASCADE_IMMEDIATE);
            if (cascade == CascadeType.ALL || cascade == CascadeType.DETACH)
                vmd.setCascadeDetach(ValueMetaData.CASCADE_IMMEDIATE);
            if (cascade == CascadeType.ALL || cascade == CascadeType.REFRESH)
                vmd.setCascadeRefresh(ValueMetaData.CASCADE_IMMEDIATE);
        }
    }

    private void setOrphanRemoval(ValueMetaData vmd, boolean orphanRemoval) {
        if (orphanRemoval)
            vmd.setCascadeDelete(ValueMetaData.CASCADE_AUTO);
    }

    /**
     * Parse @SequenceGenerator.
     */
    private void parseSequenceGenerator(AnnotatedElement el,
        SequenceGenerator gen) {
        String name = gen.name();
        if (StringUtil.isEmpty(name))
            throw new MetaDataException(_loc.get("no-seq-name", el));

        if (_log.isTraceEnabled())
            _log.trace(_loc.get("parse-sequence", name));

        SequenceMetaData meta = getRepository().getCachedSequenceMetaData
            (name);
        if (meta != null) {
            if (_log.isWarnEnabled())
                _log.warn(_loc.get("dup-sequence", name, el));
            return;
        }

        // create new sequence
        meta = getRepository().addSequenceMetaData(name);
        String seq = gen.sequenceName();
        // Do not normalize the sequence name if it appears to be a plugin
        if (seq.indexOf('(') == -1){
            seq = normalizeSequenceName(seq);
        }
        int initial = gen.initialValue();
        int allocate = gen.allocationSize();
        String schema = normalizeSchemaName(gen.schema());
        String catalog = normalizeCatalogName(gen.catalog());
        // don't allow initial of 0 b/c looks like def value
        if (initial == 0)
            initial = 1;

        // create plugin string from info
        String clsName, props;
        if (StringUtil.isEmpty(seq)) {
            clsName = SequenceMetaData.IMPL_NATIVE;
            props = null;
        } else if (seq.indexOf('(') != -1) // plugin
        {
            clsName = Configurations.getClassName(seq);
            props = Configurations.getProperties(seq);
            seq = null;
        } else {
            clsName = SequenceMetaData.IMPL_NATIVE;
            props = null;
        }

        meta.setSequencePlugin(Configurations.getPlugin(clsName, props));
        meta.setSequence(seq);
        meta.setInitialValue(initial);
        meta.setAllocate(allocate);
        meta.setSchema(schema);
        meta.setCatalog(catalog);
        meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
            SourceTracker.SRC_ANNOTATIONS);
    }

    /**
     * Parse @NamedQuery.
     */
    private void parseNamedQueries(AnnotatedElement el, NamedQuery... queries) {
        QueryMetaData meta;
        for (NamedQuery query : queries) {
            if (StringUtil.isEmpty(query.name()))
                throw new MetaDataException(_loc.get("no-query-name", el));
            if (StringUtil.isEmpty(query.query()))
                throw new MetaDataException(_loc.get("no-query-string",
                    query.name(), el));

            if (_log.isTraceEnabled())
                _log.trace(_loc.get("parse-query", query.name()));

            meta = getRepository().searchQueryMetaDataByName(query.name());
            if (meta != null) {
            	Class<?> definingType = meta.getDefiningType();
                if ((definingType == null || definingType != _cls)
                  && _log.isWarnEnabled()) {
                    _log.warn(_loc.get("dup-query", query.name(), el,
                    		definingType));
                }
                continue;
            }
            meta = getRepository().addQueryMetaData(_cls, query.name());
            meta.setLanguage(JPQLParser.LANG_JPQL);
            meta.setQueryString(query.query());
            for (QueryHint hint : query.hints())
                meta.addHint(hint.name(), hint.value());
            LockModeType lmt = processNamedQueryLockModeType(query);
            if (lmt != null && lmt != LockModeType.NONE) {
                meta.addHint("openjpa.FetchPlan.ReadLockMode", lmt);
            }

            meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
                SourceTracker.SRC_ANNOTATIONS, getSourceFile() == null ? "" : getSourceFile().getPath());
            if (isMetaDataMode())
                meta.setSourceMode(MODE_META);
            else if (isMappingMode())
                meta.setSourceMode(MODE_MAPPING);
            else
                meta.setSourceMode(MODE_QUERY);
        }
    }

    /**
     * A private worker method that calculates the lock mode for an individual NamedQuery. If the NamedQuery is
     * configured to use the NONE lock mode(explicit or implicit), this method will promote the lock to a READ
     * level lock. This was done to allow for JPA1 apps to function properly under a 2.0 runtime.
     */
    private LockModeType processNamedQueryLockModeType(NamedQuery query) {
        LockModeType lmt = query.lockMode();
        if (query.lockMode() != null) {
            String lm = _conf.getLockManager();
            boolean optimistic = _conf.getOptimistic();
            if (lm != null) {
                lm = lm.toLowerCase();
                if (lm.contains("pessimistic")) {
                    if (lmt == LockModeType.NONE && !optimistic) {
                        if (_log.isWarnEnabled()) {
                            _log.warn(_loc.get("override-named-query-lock-mode", new String[] { "annotation",
                                query.name(), _cls.getName() }));
                        }
                        lmt = LockModeType.READ;
                    }
                }
            }
        }
        return lmt;
    }

    /**
     * Parse @NamedNativeQuery.
     */
    private void parseNamedNativeQueries(AnnotatedElement el,
        NamedNativeQuery... queries) {
        QueryMetaData meta;
        for (NamedNativeQuery query : queries) {
            if (StringUtil.isEmpty(query.name()))
                throw new MetaDataException(_loc.get("no-native-query-name",
                    el));
            if (StringUtil.isEmpty(query.query()))
                throw new MetaDataException(_loc.get("no-native-query-string",
                    query.name(), el));

            if (_log.isTraceEnabled())
                _log.trace(_loc.get("parse-native-query", query.name()));

            meta = getRepository().searchQueryMetaDataByName(query.name());
            if (meta != null) {
            	Class<?> defType = meta.getDefiningType();
                if ((defType != _cls) && _log.isWarnEnabled()) {
                    _log.warn(_loc.get("dup-query", query.name(), el, defType));
                }
                continue;
            }

            meta = getRepository().addQueryMetaData(null, query.name());
            meta.setLanguage(QueryLanguages.LANG_SQL);
            meta.setQueryString(query.query());
            Class<?> res = query.resultClass();
            if (ImplHelper.isManagedType(getConfiguration(), res))
                meta.setCandidateType(res);
            else if (!void.class.equals(res))
                meta.setResultType(res);

            if (!StringUtil.isEmpty(query.resultSetMapping()))
                meta.setResultSetMappingName(query.resultSetMapping());
            for (QueryHint hint : query.hints())
                meta.addHint(hint.name(), hint.value());

            meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
                SourceTracker.SRC_ANNOTATIONS, getSourceFile() == null ? "" : getSourceFile().getPath());
            if (isMetaDataMode())
                meta.setSourceMode(MODE_META);
            else if (isMappingMode())
                meta.setSourceMode(MODE_MAPPING);
            else
                meta.setSourceMode(MODE_QUERY);
        }
    }

    /**
     * Set the explicit access type, if specified.
     */
    private void parseAccess(FieldMetaData meta, Access access) {
    	if (access != null) {
    		meta.setAccessType(AccessCode.EXPLICIT
            | (access.value() == AccessType.FIELD ?
            		AccessCode.FIELD : AccessCode.PROPERTY));
    	}
    }

    private static class MethodKey {

        private final Method _method;

        public MethodKey(Method m) {
            _method = m;
        }

        @Override
        public int hashCode() {
            int code = 46 * 12 + _method.getName().hashCode();
            for (Class<?> param : _method.getParameterTypes())
                code = 46 * code + param.hashCode();
            return code;
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof MethodKey))
                return false;
            Method other = ((MethodKey) o)._method;
            if (!_method.getName().equals(other.getName()))
                return false;
            return Arrays.equals(_method.getParameterTypes(),
                other.getParameterTypes());
        }
    }

    private static class MethodComparator implements Comparator<Method> {

        private static MethodComparator INSTANCE = null;

        public static MethodComparator getInstance() {
            if (INSTANCE == null)
                INSTANCE = new MethodComparator();
            return INSTANCE;
        }

        @Override
        public int compare(Method m1, Method m2) {
            Class<?> c1 = m1.getDeclaringClass();
            Class<?> c2 = m2.getDeclaringClass();
            if (!c1.equals(c2)) {
                if (c1.isAssignableFrom(c2))
                    return -1;
                else
                    return 1;
            }
            int compare = m1.getName().compareTo(m2.getName ());
            if (compare != 0) {
                return compare;
            }

            Class<?>[] params1 = m1.getParameterTypes();
            Class<?>[] params2 = m2.getParameterTypes();
            compare = params1.length - params2.length;
            if (compare != 0) {
                return compare;
            }

            // Just using the Method#hashCode() is not enough as it only contains
            // the hash of the class + the hash of the NAME of the method...
            // Thus if they have the same number of parameters, we need to compare them all
            for (int i = 0; i < params1.length; i++) {
                compare = params1[i].hashCode() - params2[i].hashCode();
                if (compare != 0) {
                    return compare;
                }
            }

            return 0;
        }
    }

    /**
     * An internal class used to mimic the FetchGroup annotation.
     * This is needed to process the fetch-group element in xml
     * metadata with common code for the annotation.
     */
    static class FetchGroupImpl {
        private String name = "";
        private boolean postLoad = false;
        private FetchAttributeImpl[] attributes = {};
        private String[] fetchGroups = {};

        FetchGroupImpl(String name, boolean postLoad)
        {
            this.name = name;
            this.postLoad = postLoad;
        }

        public String name() {
            return name;
        }

        public boolean postLoad() {
            return postLoad;
        }

        public FetchAttributeImpl[] attributes() {
            return attributes;
        }

        public String[] fetchGroups() {
            return fetchGroups;
        }


        public void setAttributes(FetchAttributeImpl[] attributes) {
            this.attributes = attributes;
        }

        public void setFetchGroups(String[] fetchGroups) {
            this.fetchGroups = fetchGroups;
        }
    }

    /**
     * An internal class used to mimic the FetchAttribute annotation.
     * This is needed to process the fetch-attribute element in xml
     * metadata with common code for the annotation.
     */
    static class FetchAttributeImpl {
        private String name = "";
        private int recursionDepth = Integer.MIN_VALUE;

        public FetchAttributeImpl(String name, int recursionDepth) {
            this.name = name;
            this.recursionDepth = recursionDepth;
        }

        public String name() {
            return name;
        }

        public int recursionDepth() {
            return recursionDepth;
        }


    }

    protected String normalizeSequenceName(String seqName) {
        return seqName;
    }

    protected String normalizeSchemaName(String schName) {
        return schName;
    }

    protected String normalizeCatalogName(String catName) {
        return catName;
    }


    protected MultiQueryMetaData.Parameter.Mode toKernelParameterMode(ParameterMode mode) {
        switch (mode) {
            case IN : return MultiQueryMetaData.Parameter.Mode.IN;
            case OUT: return MultiQueryMetaData.Parameter.Mode.OUT;
            case INOUT: return MultiQueryMetaData.Parameter.Mode.INOUT;
            case REF_CURSOR: return MultiQueryMetaData.Parameter.Mode.CURSOR;
            default : return MultiQueryMetaData.Parameter.Mode.IN;
        }
    }

    protected void addSourceInfo(AnnotatedElement el, QueryMetaData meta) {
        meta.setSource(getSourceFile(), (el instanceof Class) ? el : null,
                SourceTracker.SRC_ANNOTATIONS, getSourceFile() == null ? "" : getSourceFile().getPath());
        if (isMetaDataMode())
            meta.setSourceMode(MODE_META);
        else if (isMappingMode())
            meta.setSourceMode(MODE_MAPPING);
        else
            meta.setSourceMode(MODE_QUERY);
    }

    protected void addHints(QueryMetaData meta, QueryHint...hints) {
        for (QueryHint hint : hints)
            meta.addHint(hint.name(), hint.value());

    }

    private void parseNamedStoredProcedureQueries(AnnotatedElement el, NamedStoredProcedureQuery... procs) {
        for (NamedStoredProcedureQuery proc : procs) {
            if (StringUtil.isEmpty(proc.name()))
                throw new MetaDataException(_loc.get("stored-proc-no-name", el));
            if (StringUtil.isEmpty(proc.procedureName()))
                throw new MetaDataException(_loc.get("stored-proc-no-dbname", el));

            // Query metadata name
            MultiQueryMetaData meta = new MultiQueryMetaData(_cls, proc.name(), proc.procedureName(), false);
            QueryMetaData existing = getRepository().addQueryMetaData(meta);
            if (existing != null && existing.getDefiningType() != meta.getDefiningType()) {
                getLog().warn(_loc.get("dup-query", meta.getName(), el, existing.getDefiningType()));
            }

            // Important: The query string is the name of the database stored procedure
            meta.setQueryString(proc.procedureName());

            // For each mapping name/result class, add a component metadata
            // The spec restricts that either ResultMappingName or ResultClasses be specified, but not both.
            // This is relevant because the order of mapping must match the order in which the
            // components are returned
            Class<?>[] resultClasses = proc.resultClasses();
            String[] resultSetMappings = proc.resultSetMappings();
            if (resultClasses.length > 0 && resultSetMappings.length > 0)
                throw new MetaDataException(_loc.get("stored-proc-both-mapping", el));
            for (Class<?> res : resultClasses) {
                meta.addComponent(res);
            }
            for (String mapping : resultSetMappings) {
                meta.addComponent(mapping);
            }
            StoredProcedureParameter[] params = proc.parameters();
            for (StoredProcedureParameter param : params) {
                MultiQueryMetaData.Parameter p = new MultiQueryMetaData.Parameter(
                        param.name(), param.type(), toKernelParameterMode(param.mode()));
                meta.registerParameter(p);
            }
            addHints(meta, proc.hints());
            addSourceInfo(el, meta);
        }
    }
}

