/*
 * 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 java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;

import javax.persistence.AttributeOverride;
import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.EmbeddedId;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.MapKey;
import javax.persistence.MappedSuperclass;
import javax.persistence.NamedNativeQuery;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.OrderBy;
import javax.persistence.QueryHint;
import javax.persistence.SequenceGenerator;
import javax.persistence.Transient;
import javax.persistence.Version;

import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.kernel.QueryLanguages;
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.ClassUtil;
import org.apache.openjpa.lib.util.J2DoPrivHelper;
import org.apache.openjpa.lib.util.JavaVersions;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.meta.MetaDataInheritanceComparator;
import org.apache.openjpa.meta.MetaDataModes;
import org.apache.openjpa.meta.MetaDataRepository;
import org.apache.openjpa.meta.Order;
import org.apache.openjpa.meta.QueryMetaData;
import org.apache.openjpa.meta.SequenceMetaData;
import org.apache.openjpa.meta.ValueMetaData;
import org.apache.openjpa.util.InternalException;


//@todo: javadocs

/**
 * Serializes persistence metadata as annotations.
 * This class processes all object level tags that are store-agnostic.
 * However, it provides hooks for the subclasses to include store-specific
 * tags to be serialized both at &lt;entity-mappings&gt; and
 * &lt;entity&gt; level.
 *
 * @since 1.0.0
 * @author Steve Kim
 * @author Gokhan Ergul
 */
public class AnnotationPersistenceMetaDataSerializer
    implements PersistenceMetaDataFactory.Serializer {

    // NOTE: order is important! these constants must be maintained in
    // serialization order. constants are spaced so that subclasses can
    // slip tags in-between
    protected static final int TYPE_SEQ = 10;
    protected static final int TYPE_QUERY = 20;
    protected static final int TYPE_META = 30;
    protected static final int TYPE_CLASS_SEQS = 40;
    protected static final int TYPE_CLASS_QUERIES = 50;

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

    private Log _log = null;
    
    private final OpenJPAConfiguration _conf;
    private Map<String, ClassMetaData> _metas = null;
    private Map<String, List> _queries = null;
    private Map<String, List> _seqs = null;
    private int _mode = MetaDataModes.MODE_NONE;
    private SerializationComparator _comp = null;

    private Map<ClassMetaData, List<AnnotationBuilder>> _clsAnnos = null;
    private Map<FieldMetaData, List<AnnotationBuilder>> _fldAnnos = null;
    private Map<SequenceMetaData, List<AnnotationBuilder>> _seqAnnos = null;
    private Map<QueryMetaData, List<AnnotationBuilder>> _qryAnnos = null; 

    /**
     * Constructor. Supply configuration.
     */
    public AnnotationPersistenceMetaDataSerializer(OpenJPAConfiguration conf) {
        _conf = conf;
        setLog(conf.getLog(OpenJPAConfiguration.LOG_METADATA));
        setMode(MetaDataModes.MODE_META | MetaDataModes.MODE_MAPPING |
            MetaDataModes.MODE_QUERY);
    }

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

    /**
     * The log to write to.
     */
    public Log getLog() {
        return _log;
    }

    /**
     * The log to write to.
     */
    public void setLog(Log log) {
        _log = log;
    }
    
    /**
     * The serialization mode according to the expected document type. The
     * mode constants act as bit flags, and therefore can be combined.
     */
    public int getMode() {
        return _mode;
    }

    /**
     * The serialization mode according to the expected document type. The
     * mode constants act as bit flags, and therefore can be combined.
     */
    public void setMode(int mode) {
        _mode = mode;
    }

    /**
     * The serialization mode according to the expected document type.
     */
    public void setMode(int mode, boolean on) {
        if (mode == MetaDataModes.MODE_NONE)
            setMode(MetaDataModes.MODE_NONE);
        else if (on)
            setMode(_mode | mode);
        else
            setMode(_mode & ~mode);
    }

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

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

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

    /**
     * Convenience method for interpreting {@link #getMode}. Takes into
     * account whether mapping information is loaded for the given instance.
     * OPENJPA-1360 - Allow @Column attributes when meta.isEmbeddedOnly()
     */
    protected boolean isMappingMode(ClassMetaData meta) {
        return isMappingMode() && (meta.getSourceMode()
            & MetaDataModes.MODE_MAPPING) != 0
            && (meta.getEmbeddingMetaData() == null
            || isMappingMode(meta.getEmbeddingMetaData()));
    }

    /**
     * Convenience method for interpreting {@link #getMode}. Takes into
     * account whether mapping information is loaded for the given instance.
     */
    protected boolean isMappingMode(ValueMetaData vmd) {
        return isMappingMode(vmd.getFieldMetaData().getDefiningMetaData());
    }

    /**
     * Add a class meta data to the set to be serialized.
     */
    public void addMetaData(ClassMetaData meta) {
        if (meta == null)
            return;

        if (_metas == null)
            _metas = new HashMap<String, ClassMetaData>();
        _metas.put(meta.getDescribedType().getName(), meta);
    }

    /**
     * Add a sequence meta data to the set to be serialized.
     */
    public void addSequenceMetaData(SequenceMetaData meta) {
        if (meta == null)
            return;

        List seqs = null;
        String defName = null;
        if (meta.getSourceScope() instanceof Class)
            defName = ((Class) meta.getSourceScope()).getName();
        if (_seqs == null)
            _seqs = new HashMap<String, List>();
        else
            seqs = _seqs.get(defName);

        if (seqs == null) {
            seqs = new ArrayList(3); // don't expect many seqs / class
            seqs.add(meta);
            _seqs.put(defName, seqs);
        } else if (!seqs.contains(meta))
            seqs.add(meta);
    }

    /**
     * Add a query meta data to the set to be serialized.
     */
    public void addQueryMetaData(QueryMetaData meta) {
        if (meta == null)
            return;

        List queries = null;
        String defName = null;
        if (meta.getSourceScope() instanceof Class)
            defName = ((Class) meta.getSourceScope()).getName();
        if (_queries == null)
            _queries = new HashMap<String, List>();
        else
            queries = _queries.get(defName);

        if (queries == null) {
            queries = new ArrayList(3); // don't expect many queries / class
            queries.add(meta);
            _queries.put(defName, queries);
        } else if (!queries.contains(meta))
            queries.add(meta);
    }

    /**
     * Add all components in the given repository to the set to be serialized.
     */
    public void addAll(MetaDataRepository repos) {
        if (repos == null)
            return;

        for (ClassMetaData meta : repos.getMetaDatas())
            addMetaData(meta);
        for (SequenceMetaData seq : repos.getSequenceMetaDatas())
            addSequenceMetaData(seq);
        for (QueryMetaData query : repos.getQueryMetaDatas())
            addQueryMetaData(query);
    }

    /**
     * Remove a metadata from the set to be serialized.
     *
     * @return true if removed, false if not in set
     */
    public boolean removeMetaData(ClassMetaData meta) {
        return _metas != null && meta != null
            && _metas.remove(meta.getDescribedType().getName()) != null;
    }

    /**
     * Remove a sequence metadata from the set to be serialized.
     *
     * @return true if removed, false if not in set
     */
    public boolean removeSequenceMetaData(SequenceMetaData meta) {
        if (_seqs == null || meta == null)
            return false;
        String defName = null;
        if (meta.getSourceScope() instanceof Class)
            defName = ((Class) meta.getSourceScope()).getName();
        List seqs = _seqs.get(defName);
        if (seqs == null)
            return false;
        if (!seqs.remove(meta))
            return false;
        if (seqs.isEmpty())
            _seqs.remove(defName);
        return true;
    }

    /**
     * Remove a query metadata from the set to be serialized.
     *
     * @return true if removed, false if not in set
     */
    public boolean removeQueryMetaData(QueryMetaData meta) {
        if (_queries == null || meta == null)
            return false;
        String defName = null;
        if (meta.getSourceScope() instanceof Class)
            defName = ((Class) meta.getSourceScope()).getName();
        List queries = _queries.get(defName);
        if (queries == null)
            return false;
        if (!queries.remove(meta))
            return false;
        if (queries.isEmpty())
            _queries.remove(defName);
        return true;
    }

    /**
     * Remove all the components in the given repository from the set to be
     * serialized.
     *
     * @return true if any components removed, false if none in set
     */
    public boolean removeAll(MetaDataRepository repos) {
        if (repos == null)
            return false;

        boolean removed = false;
        ClassMetaData[] metas = repos.getMetaDatas();
        for (int i = 0; i < metas.length; i++)
            removed |= removeMetaData(metas[i]);
        SequenceMetaData[] seqs = repos.getSequenceMetaDatas();
        for (int i = 0; i < seqs.length; i++)
            removed |= removeSequenceMetaData(seqs[i]);
        QueryMetaData[] queries = repos.getQueryMetaDatas();
        for (int i = 0; i < queries.length; i++)
            removed |= removeQueryMetaData(queries[i]);
        return removed;
    }

    /**
     * Clear the set of metadatas to be serialized.
     */
    public void clear() {
        if (_metas != null)
            _metas.clear();
        if (_seqs != null)
            _seqs.clear();
        if (_queries != null)
            _queries.clear();
    }

    /**
     * Add system-level mapping elements to be serialized. Does nothing
     * by default.
     */
    protected void addSystemMappingElements(Collection toSerialize) {
    }

    /**
     * Sort the given collection of objects to be serialized.
     */
    private void serializationSort(List objs) {
        if (objs == null || objs.isEmpty())
            return;
        if (_comp == null)
            _comp = newSerializationComparator();
        Collections.sort(objs, _comp);
    }

    /**
     * Create a new comparator for ordering objects that are to be serialized.
     */
    protected SerializationComparator newSerializationComparator() {
        return _comp;
    }

    /**
     * Add sequence metadata to the given metadatas collection.
     */
    private void addSequenceMetaDatas(Collection all) {
        if (_seqs == null)
            return;

        for (Map.Entry entry : _seqs.entrySet()) {
            if (entry.getKey() == null)
                all.addAll((List) entry.getValue());
            else if (_metas == null || !_metas.containsKey(entry.getKey()))
                all.add(new ClassSeqs((List<SequenceMetaData>)
                    entry.getValue()));
        }
    }

    /**
     * Add query metadata to the given metadatas collection.
     */
    private void addQueryMetaDatas(Collection all) {
        if (_queries == null)
            return;

        for (Map.Entry entry : _queries.entrySet()) {
            if (entry.getKey() == null)
                all.addAll((List) entry.getValue());
            else if (_mode == MetaDataModes.MODE_QUERY || _metas == null
                || !_metas.containsKey(entry.getKey()))
                all.add(new ClassQueries((List<QueryMetaData>)
                    entry.getValue()));
        }
    }

    /**
     * Creates a new annotation builder for the specified annotation type.
     */
    protected AnnotationBuilder newAnnotationBuilder(
        Class<? extends Annotation> annType) {
        return new AnnotationBuilder(annType);        
    }

    protected void addAnnotation(AnnotationBuilder ab, Object meta) {
        if (meta instanceof ClassMetaData)
            addAnnotation(ab, (ClassMetaData) meta);
        else if (meta instanceof FieldMetaData)
            addAnnotation(ab, (FieldMetaData) meta);
        else if (meta instanceof SequenceMetaData)
            addAnnotation(ab, (SequenceMetaData) meta);
        else if (meta instanceof QueryMetaData)
            addAnnotation(ab, (QueryMetaData) meta);
    }

    /**
     * Add an annotation builder to list of builders for the specified
     * class metadata.
     */
    protected void addAnnotation(AnnotationBuilder ab, ClassMetaData meta) {
        if (_clsAnnos == null)
            _clsAnnos = new HashMap<ClassMetaData, List<AnnotationBuilder>>();
        List<AnnotationBuilder> list = _clsAnnos.get(meta);
        if (list == null) {
            list = new ArrayList<AnnotationBuilder>();
            _clsAnnos.put(meta, list);
        }
        list.add(ab);        
    }

    /**
     * Add an annotation builder to list of builders for the specified
     * field metadata.
     */
    protected void addAnnotation(AnnotationBuilder ab, FieldMetaData meta) {
        if (_fldAnnos == null)
            _fldAnnos = new HashMap<FieldMetaData, List<AnnotationBuilder>>();
        List<AnnotationBuilder> list = _fldAnnos.get(meta);
        if (list == null) {
            list = new ArrayList<AnnotationBuilder>();
            _fldAnnos.put(meta, list);
        }
        list.add(ab);
    }

    /**
     * Add an annotation builder to list of builders for the specified
     * sequence metadata.
     */
    protected void addAnnotation(AnnotationBuilder ab, SequenceMetaData meta) {
        if (_seqAnnos == null)
            _seqAnnos = new HashMap<SequenceMetaData,
                    List<AnnotationBuilder>>();
        List<AnnotationBuilder> list = _seqAnnos.get(meta);
        if (list == null) {
            list = new ArrayList<AnnotationBuilder>();
            _seqAnnos.put(meta, list);
        }
        list.add(ab);
    }

    /**
     * Add an annotation builder to list of builders for the specified
     * query metadata.
     */
    protected void addAnnotation(AnnotationBuilder ab, QueryMetaData meta) {
        if (_qryAnnos == null)
            _qryAnnos = new HashMap<QueryMetaData, List<AnnotationBuilder>>();
        List<AnnotationBuilder> list = _qryAnnos.get(meta);
        if (list == null) {
            list = new ArrayList<AnnotationBuilder>();
            _qryAnnos.put(meta, list);
        }
        list.add(ab);
    }

    /**
     * Creates an an annotation builder for the specified class metadata
     * and adds it to list of builders.
     */
    protected AnnotationBuilder addAnnotation(
        Class<? extends Annotation> annType, ClassMetaData meta) {
        AnnotationBuilder ab = newAnnotationBuilder(annType);
        if (meta == null)
            return ab;
        addAnnotation(ab, meta);
        return ab;
    }

    /**
     * Creates an an annotation builder for the specified class metadata
     * and adds it to list of builders.
     */
    protected AnnotationBuilder addAnnotation(
        Class<? extends Annotation> annType, FieldMetaData meta) {
        AnnotationBuilder ab = newAnnotationBuilder(annType);
        if (meta == null)
            return ab;
        addAnnotation(ab, meta);
        return ab;
    }

    /**
     * Creates an an annotation builder for the specified class metadata
     * and adds it to list of builders.
     */
    protected AnnotationBuilder addAnnotation(
        Class<? extends Annotation> annType, SequenceMetaData meta) {
        AnnotationBuilder ab = newAnnotationBuilder(annType);
        if (meta == null)
            return ab;
        addAnnotation(ab, meta);
        return ab;
    }

    /**
     * Creates an an annotation builder for the specified class metadata
     * and adds it to list of builders.
     */
    protected AnnotationBuilder addAnnotation(
        Class<? extends Annotation> annType, QueryMetaData meta) {
        AnnotationBuilder ab = newAnnotationBuilder(annType);
        if (meta == null)
            return ab;
        addAnnotation(ab, meta);
        return ab;
    }
    
    protected void serialize(Collection objects) {
        for (Object obj : objects) {
            int type = type(obj);
            switch (type) {
                case TYPE_META:
                    serializeClass((ClassMetaData) obj);
                    break;
                case TYPE_SEQ:
                    if (isMappingMode())
                        serializeSequence((SequenceMetaData) obj);
                    break;
                case TYPE_QUERY:
                    serializeQuery((QueryMetaData) obj);
                    break;
                case TYPE_CLASS_QUERIES:
                    for (QueryMetaData query : ((ClassQueries) obj)
                        .getQueries())
                        serializeQuery(query);
                    break;
                case TYPE_CLASS_SEQS:
                    if (isMappingMode())
                        for (SequenceMetaData seq : ((ClassSeqs) obj)
                            .getSequences())
                            serializeSequence(seq);
                    break;
                default:
                    if (isMappingMode())
                        serializeSystemMappingElement(obj);
                    break;
            }
        }
    }

    /**
     * Return the type constant for the given object based on its runtime
     * class. If the runtime class does not correspond to any of the known
     * types then returns -1. This can happen for tags
     * that are not handled at this store-agnostic level.
     */
    protected int type(Object o) {
        if (o instanceof ClassMetaData)
            return TYPE_META;
        if (o instanceof QueryMetaData)
            return TYPE_QUERY;
        if (o instanceof SequenceMetaData)
            return TYPE_SEQ;
        if (o instanceof ClassQueries)
            return TYPE_CLASS_QUERIES;
        if (o instanceof ClassSeqs)
            return TYPE_CLASS_SEQS;
        return -1;
    }

    /**
     * Serialize unknown mapping element at system level.
     */
    protected void serializeSystemMappingElement(Object obj) {
    }

    /**
     * Serialize query metadata.
     */
    private void serializeQuery(QueryMetaData meta) {
        Log log = getLog();
        if (log.isInfoEnabled()) {
            if (meta.getSourceScope() instanceof Class)
                log.info(_loc.get("ser-cls-query",
                    meta.getSourceScope(), meta.getName()));
            else
                log.info(_loc.get("ser-query", meta.getName()));
        }

        Class<? extends Annotation> ann =
            QueryLanguages.LANG_SQL.equals(meta.getLanguage()) ?
            NamedNativeQuery.class : NamedQuery.class;
        AnnotationBuilder abQry = addAnnotation(ann, meta);
        abQry.add("name", meta.getName());
        abQry.add("query", meta.getQueryString());
        if (QueryLanguages.LANG_SQL.equals(meta.getLanguage())) {
            if (meta.getResultType() != null)
                abQry.add("resultClass", meta.getResultType());
        }
        serializeQueryHints(meta, abQry);
    }

    /**
     * Serialize query hints.
     */
    private void serializeQueryHints(QueryMetaData meta, AnnotationBuilder ab) {
        String[] hints = meta.getHintKeys();
        Object[] values = meta.getHintValues();
        for (int i = 0; i < hints.length; i++) {
            AnnotationBuilder abHint = newAnnotationBuilder(QueryHint.class);
            abHint.add("name", hints[i]);
            abHint.add("value", String.valueOf(values[i]));
            ab.add("hints", abHint);
        }
    }

    /**
     * Serialize sequence metadata.
     */
    protected void serializeSequence(SequenceMetaData meta) {
        Log log = getLog();
        if (log.isInfoEnabled())
            log.info(_loc.get("ser-sequence", meta.getName()));

        AnnotationBuilder ab = addAnnotation(SequenceGenerator.class, meta);
        ab.add("name", meta.getName());

        // parse out the datastore sequence name, if any
        String plugin = meta.getSequencePlugin();
        String clsName = Configurations.getClassName(plugin);
        String props = Configurations.getProperties(plugin);
        String ds = null;
        if (props != null) {
            Properties map = Configurations.parseProperties(props);
            ds = (String) map.remove("Sequence");
            if (ds != null) {
                props = Configurations.serializeProperties(map);
                plugin = Configurations.getPlugin(clsName, props);
            }
        }

        if (ds != null)
            ab.add("sequenceName", ds);
        else if (plugin != null && !SequenceMetaData.IMPL_NATIVE.equals
            (plugin))
            ab.add("sequenceName", plugin);
        if (meta.getInitialValue() != 0 && meta.getInitialValue() != -1)
            ab.add("initialValue", meta.getInitialValue());
        if (meta.getAllocate() != 50 && meta.getAllocate() != -1)
            ab.add("allocationSize", meta.getAllocate());
        if (meta.getSchema() != null)
            ab.add("schema", meta.getSchema());
        if (meta.getCatalog() != null)
            ab.add("catalog", meta.getCatalog());
    }

    /**
     * Serialize class metadata.
     */
    protected void serializeClass(ClassMetaData meta) {
        Log log = getLog();
        if (log.isInfoEnabled())
            log.info(_loc.get("ser-class", meta));

        AnnotationBuilder abEntity = addAnnotation(
            getEntityAnnotationType(meta), meta);
        if (isMetaDataMode()
            && !meta.getTypeAlias().equals(ClassUtil.getClassName(meta.
            getDescribedType())))
            abEntity.add("name", meta.getTypeAlias());
        
        if (isMappingMode())
            addClassMappingAnnotations(meta);

        if (isMappingMode())
            serializeClassMappingContent(meta);
        if (isMetaDataMode())
            serializeIdClass(meta);
        if (isMappingMode())
            serializeInheritanceContent(meta);

        if (isMappingMode()) {
            List seqs = (_seqs == null) ? null : _seqs.get
                (meta.getDescribedType().getName());
            if (seqs != null) {
                serializationSort(seqs);
                for (int i = 0; i < seqs.size(); i++)
                    serializeSequence((SequenceMetaData) seqs.get(i));
            }
        }

        if (isQueryMode()) {
            List queries = (_queries == null) ? null : _queries.get
                (meta.getDescribedType().getName());
            if (queries != null) {
                serializationSort(queries);
                for (int i = 0; i < queries.size(); i++)
                    serializeQuery((QueryMetaData) queries.get(i));
            }
            if (isMappingMode())
                serializeQueryMappings(meta);
        }

        List<FieldMetaData> fields = new ArrayList(Arrays.asList
            (meta.getDefinedFieldsInListingOrder()));
        Collections.sort(fields, new FieldComparator());

        // serialize attr-override
        if (isMappingMode()) {
            FieldMetaData fmd;
            FieldMetaData orig;
            for (Iterator<FieldMetaData> it = fields.iterator(); it.hasNext();)
            {
                fmd = it.next();
                if (meta.getDefinedSuperclassField(fmd.getName()) == null)
                    continue;
                orig = meta.getPCSuperclassMetaData().getField(fmd.getName());
                if (serializeAttributeOverride(fmd, orig))
                    serializeAttributeOverrideContent(fmd, orig);
                it.remove();
            }
        }

        if (fields.size() > 0 && (isMetaDataMode() || isMappingMode())) {
            FieldMetaData orig;
            for (FieldMetaData fmd : fields) {
                if (fmd.getDeclaringType() != fmd.getDefiningMetaData().
                    getDescribedType()) {
                    orig = fmd.getDeclaringMetaData().getDeclaredField
                        (fmd.getName());
                } else
                    orig = null;
                serializeField(fmd, orig);
            }
        }
    }

    /**
     * Return entity annotation type.
     */
    private static Class<? extends Annotation> getEntityAnnotationType(
        ClassMetaData meta) {
        switch (getEntityTag(meta)) {
            case ENTITY:
                return Entity.class;
            case EMBEDDABLE:
                return Embeddable.class;
            case MAPPED_SUPERCLASS:
                return MappedSuperclass.class;
            default:
                throw new IllegalStateException();
        }
    }

    /**
     * Return field annotation type.
     */
    private static Class<? extends Annotation> getFieldAnnotationType (
        FieldMetaData fmd, PersistenceStrategy strat) {
        Class<? extends Annotation> ann = null;
        if (fmd.isPrimaryKey() && strat == PersistenceStrategy.EMBEDDED)
            ann = EmbeddedId.class;
        else if (fmd.isPrimaryKey())
            ann = Id.class;
        else if (fmd.isVersion())
            ann = Version.class;
        else {
            switch (strat) {
                case TRANSIENT:
                    ann = Transient.class;
                    break;
                case BASIC:
                    ann = Basic.class;
                    break;
                case EMBEDDED:
                    ann = Embedded.class;
                    break;
                case MANY_ONE:
                    ann = ManyToOne.class;
                    break;
                case ONE_ONE:
                    ann = OneToOne.class;
                    break;
                case ONE_MANY:
                    ann = OneToMany.class;
                    break;
                case MANY_MANY:
                    ann = ManyToMany.class;
                    break;
            }
        }
        return ann;
    }

    /**
     * Return the MetaDataTag for the given class meta data.
     */
    private static MetaDataTag getEntityTag(ClassMetaData meta) {
        if (meta.isAbstract())
            return MetaDataTag.MAPPED_SUPERCLASS;
        // @Embeddable classes can't declare Id fields
        if (meta.isEmbeddedOnly() && meta.getPrimaryKeyFields().length == 0)
            return MetaDataTag.EMBEDDABLE;
        if (meta.isMapped())
            return MetaDataTag.ENTITY;
        return MetaDataTag.MAPPED_SUPERCLASS;
    }

    /**
     * Add mapping attributes for the given class. Does nothing by default
     */
    protected void addClassMappingAnnotations(ClassMetaData mapping) {
    }

    /**
     * Serialize id-class.
     */
    private void serializeIdClass(ClassMetaData meta) {
        if (meta.getIdentityType() != ClassMetaData.ID_APPLICATION
            || meta.isOpenJPAIdentity())
            return;

        ClassMetaData sup = meta.getPCSuperclassMetaData();
        Class oid = meta.getObjectIdType();
        if (oid != null && (sup == null || oid != sup.getObjectIdType())) {
            AnnotationBuilder ab = addAnnotation(IdClass.class, meta);
            ab.add(null, oid);
        }
    }

    /**
     * Serialize class mapping content. Does nothing by default.
     */
    protected void serializeClassMappingContent(ClassMetaData mapping) {
    }

    /**
     * Serialize inheritance content. Does nothing by default.
     */
    protected void serializeInheritanceContent(ClassMetaData mapping) {
    }

    /**
     * Serialize query mappings. Does nothing by default.
     */
    protected void serializeQueryMappings(ClassMetaData meta) {
    }

    /**
     * Serialize the given field.
     */
    private void serializeField(FieldMetaData fmd, FieldMetaData orig) {
        if (fmd.getManagement() != FieldMetaData.MANAGE_PERSISTENT
            && !fmd.isExplicit())
            return;

        PersistenceStrategy strat = getStrategy(fmd);
        ValueMetaData cascades = null;
        AnnotationBuilder ab = addAnnotation(
            getFieldAnnotationType (fmd, strat), fmd);        
        if (fmd.isPrimaryKey() && strat == PersistenceStrategy.EMBEDDED)
            ; // noop
        else if (fmd.isPrimaryKey())
            ; // noop
        else if (fmd.isVersion())
            ; // noop
        else {
            switch (strat) {
                case BASIC:
                    if (isMetaDataMode())
                        addBasicAttributes(fmd, ab);
                    break;
                case MANY_ONE:
                    if (isMetaDataMode())
                        addManyToOneAttributes(fmd, ab);
                    cascades = fmd;
                    break;
                case ONE_ONE:
                    if (isMetaDataMode())
                        addOneToOneAttributes(fmd, ab);
                    cascades = fmd;
                    break;
                case ONE_MANY:
                    if (isMetaDataMode())
                        addOneToManyAttributes(fmd, ab);
                    cascades = fmd.getElement();
                    break;
                case MANY_MANY:
                    if (isMetaDataMode())
                        addManyToManyAttributes(fmd, ab);
                    cascades = fmd.getElement();
                    break;
            }
            if (isMappingMode())
                addStrategyMappingAttributes(fmd, ab);
        }
        if (isMappingMode(fmd))
            addFieldMappingAttributes(fmd, orig, ab);

        if (fmd.getOrderDeclaration() != null) {
            if (!(Order.ELEMENT + " asc").equals(fmd.getOrderDeclaration()))
                addAnnotation(OrderBy.class, fmd).
                    add (null, fmd.getOrderDeclaration());
        }
        if (isMappingMode() && fmd.getKey().getValueMappedBy() != null) {
            AnnotationBuilder abMapKey = addAnnotation(MapKey.class, fmd);
            FieldMetaData mapBy = fmd.getKey().getValueMappedByMetaData();
            if (!mapBy.isPrimaryKey() ||
                mapBy.getDefiningMetaData().getPrimaryKeyFields().length != 1) {
                abMapKey.add("name", fmd.getKey().getValueMappedBy());
            }
        }
        if (isMappingMode(fmd))
            serializeFieldMappingContent(fmd, strat, ab);
        if (cascades != null && isMetaDataMode())
            serializeCascades(cascades, ab);
    }

    /**
     * Add mapping attributes for the given field. Does nothing by default.
     */
    protected void addFieldMappingAttributes(FieldMetaData fmd,
        FieldMetaData orig, AnnotationBuilder ab) {
    }
    
    /**
     * Always returns false by default.
     */
    protected boolean serializeAttributeOverride(FieldMetaData fmd,
        FieldMetaData orig) {
        return false;
    }

    /**
     * Serialize attribute override content.
     */
    private void serializeAttributeOverrideContent(FieldMetaData fmd,
        FieldMetaData orig) {
        AnnotationBuilder ab = addAnnotation(AttributeOverride.class, fmd);
        ab.add("name", fmd.getName());
        serializeAttributeOverrideMappingContent(fmd, orig, ab);
    }

    /**
     * Serialize attribute override mapping content. Does nothing by default,
     */
    protected void serializeAttributeOverrideMappingContent
        (FieldMetaData fmd, FieldMetaData orig, AnnotationBuilder ab) {
    }


    /**
     * Serialize cascades.
     */
    private void serializeCascades(ValueMetaData vmd, AnnotationBuilder ab) {
        EnumSet<CascadeType> cascades = EnumSet.noneOf(CascadeType.class);
        if (vmd.getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) {
            cascades.add(CascadeType.PERSIST);
        }
        if (vmd.getCascadeAttach() == ValueMetaData.CASCADE_IMMEDIATE) {
            cascades.add(CascadeType.MERGE);
        }
        if (vmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE) {
            cascades.add(CascadeType.REMOVE);
        }
        if (vmd.getCascadeRefresh() == ValueMetaData.CASCADE_IMMEDIATE) {
            cascades.add(CascadeType.REFRESH);
        }
        if (vmd.getCascadeDetach() == ValueMetaData.CASCADE_IMMEDIATE) {
            cascades.add(CascadeType.DETACH);
        }
        if (cascades.size() == 5) // ALL
        {
            cascades.clear();
            cascades.add(CascadeType.ALL);
        }
        if (!cascades.isEmpty()) {
            ab.add("cascade", cascades);
        }
    }

    /**
     * Return the serialized strategy name.
     */
    protected PersistenceStrategy getStrategy(FieldMetaData fmd) {
        if (fmd.getManagement() == fmd.MANAGE_NONE)
            return PersistenceStrategy.TRANSIENT;

        if (fmd.isSerialized()
            || fmd.getDeclaredType() == byte[].class
            || fmd.getDeclaredType() == Byte[].class
            || fmd.getDeclaredType() == char[].class
            || fmd.getDeclaredType() == Character[].class)
            return PersistenceStrategy.BASIC;

        FieldMetaData mappedBy;
        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.PC:
                if (fmd.isEmbedded())
                    return PersistenceStrategy.EMBEDDED;
                if (fmd.getMappedBy() != null)
                    return PersistenceStrategy.ONE_ONE;
                FieldMetaData[] inverses = fmd.getInverseMetaDatas();
                if (inverses.length == 1 &&
                    inverses[0].getTypeCode() == JavaTypes.PC &&
                    inverses[0].getMappedByMetaData() == fmd) {
                    return PersistenceStrategy.ONE_ONE;
                }
                return PersistenceStrategy.MANY_ONE;
            case JavaTypes.ARRAY:
            case JavaTypes.COLLECTION:
            case JavaTypes.MAP:
                mappedBy = fmd.getMappedByMetaData();
                if (mappedBy == null || mappedBy.getTypeCode() != JavaTypes.PC)
                    return PersistenceStrategy.MANY_MANY;
                return PersistenceStrategy.ONE_MANY;
            case JavaTypes.OID:
                return PersistenceStrategy.EMBEDDED;
            default:
                return PersistenceStrategy.BASIC;
        }
    }

    /**
     * Add basic attributes.
     */
    private void addBasicAttributes(FieldMetaData fmd, AnnotationBuilder ab) {
        if (!fmd.isInDefaultFetchGroup())
            ab.add("fetch", FetchType.LAZY);
        if (fmd.getNullValue() == FieldMetaData.NULL_EXCEPTION)
            ab.add("optional", false);
    }

    /**
     * Add many-to-one attributes.
     */
    private void addManyToOneAttributes(FieldMetaData fmd,
        AnnotationBuilder ab) {
        if (!fmd.isInDefaultFetchGroup())
            ab.add("fetch", FetchType.LAZY);
        if (fmd.getNullValue() == FieldMetaData.NULL_EXCEPTION)
            ab.add("optional", false);
    }

    /**
     * Add one-to-one attributes.
     */
    private void addOneToOneAttributes(FieldMetaData fmd,
        AnnotationBuilder ab) {
        if (!fmd.isInDefaultFetchGroup())
            ab.add("fetch", FetchType.LAZY);
        if (fmd.getNullValue() == FieldMetaData.NULL_EXCEPTION)
            ab.add("optional", false);
    }

    /**
     * Add one-to-many attributes.
     */
    private void addOneToManyAttributes(FieldMetaData fmd,
        AnnotationBuilder ab) {
        if (fmd.isInDefaultFetchGroup())
            ab.add("fetch", FetchType.EAGER);
        addTargetEntityAttribute(fmd, ab);
    }

    /**
     * Add many-to-many attributes.
     */
    private void addManyToManyAttributes(FieldMetaData fmd,
        AnnotationBuilder ab) {
        if (fmd.isInDefaultFetchGroup())
            ab.add("fetch", FetchType.EAGER);
        addTargetEntityAttribute(fmd, ab);
    }

    /**
     * Add a target-entity attribute to collection and map fields that do
     * not use generics.
     */
    private void addTargetEntityAttribute(FieldMetaData fmd,
        AnnotationBuilder ab) {
        Member member = fmd.getBackingMember();
        Class[] types;
        if (member instanceof Field)
            types = JavaVersions.getParameterizedTypes((Field) member);
        else if (member instanceof Method)
            types = JavaVersions.getParameterizedTypes((Method) member);
        else
            types = new Class[0];

        switch (fmd.getDeclaredTypeCode()) {
            case JavaTypes.COLLECTION:
                if (types.length != 1)
                    ab.add("targetEntity", fmd.getElement().getDeclaredType());
                break;
            case JavaTypes.MAP:
                if (types.length != 2)
                    ab.add("targetEntity", fmd.getElement().getDeclaredType());
                break;
        }
    }

    /**
     * Serialize field mapping content; this will be called before
     * {@link #serializeValueMappingContent}. Does nothing by default.
     */
    protected void serializeFieldMappingContent(FieldMetaData fmd, PersistenceStrategy strategy, AnnotationBuilder ab) {
    }

    /**
     * Set mapping attributes for strategy. Sets mapped-by by default.
     */
    protected void addStrategyMappingAttributes(FieldMetaData fmd,
        AnnotationBuilder ab) {
        if (fmd.getMappedBy() != null)
            ab.add("mappedBy", fmd.getMappedBy());
    }
    
    protected Collection getObjects() {
        List all = new ArrayList();
        if (isQueryMode())
            addQueryMetaDatas(all);
        if (isMappingMode())
            addSequenceMetaDatas(all);
        if ((isMetaDataMode() || isMappingMode()) && _metas != null)
            all.addAll(_metas.values());
        if (isMappingMode())
            addSystemMappingElements(all);
        serializationSort(all);
        return all;
    }

    protected void writeAnnotations(Object meta,
        List<AnnotationBuilder> builders, Map output) {
        List<String> annos = new ArrayList<String>();
        for(AnnotationBuilder ab: builders)
            annos.add(ab.toString());
        output.put(meta, annos);        
    }

    public void serialize(Map output, int flags) throws IOException {
        Collection all = getObjects();
        serialize(all);

        if (_clsAnnos != null)
            for (ClassMetaData meta : _clsAnnos.keySet())
                writeAnnotations(meta, _clsAnnos.get(meta), output);
        if (_fldAnnos != null)
            for (FieldMetaData meta : _fldAnnos.keySet())
                writeAnnotations(meta, _fldAnnos.get(meta), output);
        if (_seqAnnos != null)
            for (SequenceMetaData meta : _seqAnnos.keySet())
                writeAnnotations(meta, _seqAnnos.get(meta), output);
        if (_qryAnnos != null)
            for (QueryMetaData meta : _qryAnnos.keySet())
                writeAnnotations(meta, _qryAnnos.get(meta), output);
    }

    public void serialize(File file, int flags) throws IOException {
        try {
            FileWriter out = new FileWriter(AccessController
                .doPrivileged(J2DoPrivHelper.getCanonicalPathAction(file)),
                (flags & APPEND) > 0);
            serialize(out, flags);
            out.close();
        } catch (PrivilegedActionException pae) {
            throw (IOException) pae.getException();
        }
    }

    @SuppressWarnings("unchecked")
    public void serialize(Writer out, int flags) throws IOException {
        Map output = new HashMap();
        serialize(output, flags);

        Set<Entry> entrySet = output.entrySet();
        for(Entry entry : entrySet) {
            Object meta = entry.getKey();
            List<String> annos = (List<String>) entry.getValue();

            out.write("--"+meta.toString());
            out.write("\n");
            for(String ann: annos) {
                out.write("\t");
                out.write(ann);
                out.write("\n");
            }
        }
    }

    public void serialize(int flags) throws IOException {
        throw new UnsupportedOperationException();
    }

    /**
     * Represents ordered set of 
     * {@link org.apache.openjpa.meta.SequenceMetaData}s with a common class
     * scope.
     *
     * @author Stephen Kim
     * @author Pinaki Poddar
     */
    private static class ClassSeqs
        implements SourceTracker, Comparable<ClassSeqs>,
        Comparator<SequenceMetaData> {

        private final SequenceMetaData[] _seqs;

        public ClassSeqs(List<SequenceMetaData> seqs) {
            if (seqs == null || seqs.isEmpty())
                throw new InternalException();

            _seqs = (SequenceMetaData[]) seqs.toArray
                (new SequenceMetaData[seqs.size()]);
            Arrays.sort(_seqs, this);
        }

        public SequenceMetaData[] getSequences() {
            return _seqs;
        }

        /**
         * Compare sequence metadata on name.
         */
        public int compare(SequenceMetaData o1, SequenceMetaData o2) {
            return o1.getName().compareTo(o2.getName());
        }

        public File getSourceFile() {
            return _seqs[0].getSourceFile();
        }

        public Object getSourceScope() {
            return _seqs[0].getSourceScope();
        }

        public int getSourceType() {
            return _seqs[0].getSourceType();
        }

        public String getResourceName() {
            return _seqs[0].getResourceName();
        }

        public int getLineNumber() {
            return _seqs[0].getLineNumber();
        }

        public int getColNumber() {
            return _seqs[0].getColNumber();
        }
        
        public int compareTo(ClassSeqs other) {
            if (other == this)
                return 0;
            if (other == null)
                return -1;
            Class scope = (Class) getSourceScope();
            Class oscope = (Class) other.getSourceScope();
            return scope.getName().compareTo(oscope.getName());
        }
    }

    /**
     * Represents ordered set of {@link org.apache.openjpa.meta.QueryMetaData}s
     * with a common class scope.
     *
     * @author Stephen Kim
     * @author Pinaki Poddar
     */
    private static class ClassQueries
        implements SourceTracker, Comparable<ClassQueries>,
        Comparator<QueryMetaData> {

        private final QueryMetaData[] _queries;

        public ClassQueries(List<QueryMetaData> queries) {
            if (queries == null || queries.isEmpty())
                throw new InternalException();

            _queries = (QueryMetaData[]) queries.toArray
                (new QueryMetaData[queries.size()]);
            Arrays.sort(_queries, this);
        }

        public QueryMetaData[] getQueries() {
            return _queries;
        }

        /**
         * Compare query metadata. Normal queries appear before native queries.
         * If the given queries use same language, then their names are
         * compared.
         */
        public int compare(QueryMetaData o1, QueryMetaData o2) {
            // normal queries before native
            if (!Objects.equals(o1.getLanguage(), o2.getLanguage())) {
                if (QueryLanguages.LANG_SQL.equals(o1.getLanguage()))
                    return 1;
                else
                    return -1;
            }
            return o1.getName().compareTo(o2.getName());
        }

        public File getSourceFile() {
            return _queries[0].getSourceFile();
        }

        public Object getSourceScope() {
            return _queries[0].getSourceScope();
        }

        public int getSourceType() {
            return _queries[0].getSourceType();
        }

        public String getResourceName() {
            return _queries[0].getResourceName();
        }

        public int getLineNumber() {
            return _queries[0].getLineNumber();
        }

        public int getColNumber() {
            return _queries[0].getColNumber();
        }
        
        public int compareTo(ClassQueries other) {
            if (other == this)
                return 0;
            if (other == null)
                return -1;
            Class scope = (Class) getSourceScope();
            Class oscope = (Class) other.getSourceScope();
            return scope.getName().compareTo(oscope.getName());
        }
    }

    /**
     * Compares clases, sequences, and queries to order them for serialization.
     * Places sequences first, then classes, then queries. Sequences and
     * queries are ordered alphabetically by name. Classes are placed in
     * listing order, in inheritance order within that, and in alphabetical
     * order within that.
     *
     * @author Stephen Kim
     */
    protected class SerializationComparator
        extends MetaDataInheritanceComparator {

        public int compare(Object o1, Object o2) {
            if (o1 == o2)
                return 0;
            if (o1 == null)
                return 1;
            if (o2 == null)
                return -1;

            int t1 = type(o1);
            int t2 = type(o2);
            if (t1 != t2)
                return t1 - t2;

            switch (t1) {
                case TYPE_META:
                    return compare((ClassMetaData) o1, (ClassMetaData) o2);
                case TYPE_QUERY:
                    return compare((QueryMetaData) o1, (QueryMetaData) o2);
                case TYPE_SEQ:
                    return compare((SequenceMetaData) o1,
                        (SequenceMetaData) o2);
                case TYPE_CLASS_QUERIES:
                    return ((Comparable) o1).compareTo(o2);
                case TYPE_CLASS_SEQS:
                    return ((Comparable) o1).compareTo(o2);
                default:
                    return compareUnknown(o1, o2);
            }
        }

        /**
         * Compare two unrecognized elements of the same type. Throws
         * exception by default.
         */
        protected int compareUnknown(Object o1, Object o2) {
            throw new InternalException();
        }

        /**
         * Compare between two class metadata.
         */
        private int compare(ClassMetaData o1, ClassMetaData o2) {
            int li1 = o1.getListingIndex();
            int li2 = o2.getListingIndex();
            if (li1 == -1 && li2 == -1) {
                MetaDataTag t1 = getEntityTag(o1);
                MetaDataTag t2 = getEntityTag(o2);
                if (t1.compareTo(t2) != 0)
                    return t1.compareTo(t2);
                int inher = super.compare(o1, o2);
                if (inher != 0)
                    return inher;
                return o1.getDescribedType().getName().compareTo
                    (o2.getDescribedType().getName());
            }

            if (li1 == -1)
                return 1;
            if (li2 == -1)
                return -1;
            return li1 - li2;
        }

        /**
         * Compare query metadata.
         */
        private int compare(QueryMetaData o1, QueryMetaData o2) {
            // normal queries before native
            if (!Objects.equals(o1.getLanguage(), o2.getLanguage())) {
                if (QueryLanguages.LANG_SQL.equals(o1.getLanguage()))
                    return 1;
                else
                    return -1;
            }
            return o1.getName().compareTo(o2.getName());
        }

        /**
         * Compare sequence metadata.
         */
        private int compare(SequenceMetaData o1, SequenceMetaData o2) {
            return o1.getName().compareTo(o2.getName());
        }
    }

    /**
     * Sorts fields according to listing order, then XSD strategy order,
     * then name order.
     */
    private class FieldComparator
        implements Comparator {

        public int compare(Object o1, Object o2) {
            FieldMetaData fmd1 = (FieldMetaData) o1;
            FieldMetaData fmd2 = (FieldMetaData) o2;
            if (fmd1.isPrimaryKey()) {
                if (fmd2.isPrimaryKey())
                    return fmd1.compareTo(fmd2);
                return -1;
            }
            if (fmd2.isPrimaryKey())
                return 1;

            if (fmd1.isVersion()) {
                if (fmd2.isVersion())
                    return compareListingOrder(fmd1, fmd2);
                return getStrategy(fmd2) == PersistenceStrategy.BASIC ? 1 : -1;
			}
			if (fmd2.isVersion())
                return getStrategy(fmd1) == PersistenceStrategy.BASIC ? -1 : 1;

            int stcmp = getStrategy(fmd1).compareTo(getStrategy(fmd2));
            if (stcmp != 0)
                return stcmp;
            return compareListingOrder(fmd1, fmd2);
        }

        private int compareListingOrder(FieldMetaData fmd1, FieldMetaData fmd2){
            int lcmp = fmd1.getListingIndex() - fmd2.getListingIndex();
            if (lcmp != 0)
                return lcmp;
            return fmd1.compareTo(fmd2);
		}
	}
	
	/**
	 * Returns the stored ClassMetaData
	 */
	public Map<String, ClassMetaData> getClassMetaData() {
	    return _metas;
	}
}
