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

import static org.apache.openjpa.persistence.jdbc.MappingTag.ASSOC_OVERRIDE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.ATTR_OVERRIDE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.COLLECTION_TABLE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.COLS;
import static org.apache.openjpa.persistence.jdbc.MappingTag.COLUMN_NAME;
import static org.apache.openjpa.persistence.jdbc.MappingTag.COLUMN_RESULT;
import static org.apache.openjpa.persistence.jdbc.MappingTag.DATASTORE_ID_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.DELIMITED_IDS;
import static org.apache.openjpa.persistence.jdbc.MappingTag.DISCRIM_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.DISCRIM_VAL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.ENTITY_RESULT;
import static org.apache.openjpa.persistence.jdbc.MappingTag.ENUMERATED;
import static org.apache.openjpa.persistence.jdbc.MappingTag.FIELD_RESULT;
import static org.apache.openjpa.persistence.jdbc.MappingTag.FK;
import static org.apache.openjpa.persistence.jdbc.MappingTag.FK_COL_NAME;
import static org.apache.openjpa.persistence.jdbc.MappingTag.FK_COL_NAMES;
import static org.apache.openjpa.persistence.jdbc.MappingTag.INDEX;
import static org.apache.openjpa.persistence.jdbc.MappingTag.INHERITANCE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.JOIN_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.JOIN_TABLE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_ENUMERATED;
import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_JOIN_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.MAP_KEY_TEMPORAL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.NAME;
import static org.apache.openjpa.persistence.jdbc.MappingTag.ORDER_COLUMN;
import static org.apache.openjpa.persistence.jdbc.MappingTag.PK_JOIN_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.SECONDARY_TABLE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.SQL_RESULT_SET_MAPPING;
import static org.apache.openjpa.persistence.jdbc.MappingTag.TABLE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.TABLE_GEN;
import static org.apache.openjpa.persistence.jdbc.MappingTag.TEMPORAL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.UNIQUE;
import static org.apache.openjpa.persistence.jdbc.MappingTag.VERSION_COL;
import static org.apache.openjpa.persistence.jdbc.MappingTag.VERSION_COLS;

import java.lang.reflect.Modifier;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.DiscriminatorType;
import javax.persistence.EnumType;
import javax.persistence.InheritanceType;
import javax.persistence.TemporalType;

import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.QualifiedDBIdentifier;
import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
import org.apache.openjpa.jdbc.meta.ClassMapping;
import org.apache.openjpa.jdbc.meta.ClassMappingInfo;
import org.apache.openjpa.jdbc.meta.DiscriminatorMappingInfo;
import org.apache.openjpa.jdbc.meta.FieldMapping;
import org.apache.openjpa.jdbc.meta.FieldMappingInfo;
import org.apache.openjpa.jdbc.meta.MappingInfo;
import org.apache.openjpa.jdbc.meta.MappingRepository;
import org.apache.openjpa.jdbc.meta.QueryResultMapping;
import org.apache.openjpa.jdbc.meta.QueryResultMapping.PCResult;
import org.apache.openjpa.jdbc.meta.SequenceMapping;
import org.apache.openjpa.jdbc.meta.strats.EnumValueHandler;
import org.apache.openjpa.jdbc.meta.strats.FlatClassStrategy;
import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
import org.apache.openjpa.jdbc.meta.strats.VerticalClassStrategy;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Unique;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.lib.meta.SourceTracker;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.lib.util.StringUtil;
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.persistence.XMLPersistenceMetaDataParser;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.UserException;
import org.xml.sax.Attributes;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
/**
 * Custom SAX parser used by the system to parse persistence mapping files.
 *
 * @author Steve Kim
 */
public class XMLPersistenceMappingParser
    extends XMLPersistenceMetaDataParser {

    private static final Map<String, MappingTag> _elems =
        new HashMap<>();

    static {
        _elems.put("association-override", ASSOC_OVERRIDE);
        _elems.put("attribute-override", ATTR_OVERRIDE);
        _elems.put("collection-table", COLLECTION_TABLE);
        _elems.put("column", COL);
        _elems.put("columns", COLS);
        _elems.put("column-name", COLUMN_NAME);
        _elems.put("column-result", COLUMN_RESULT);
        _elems.put("data-store-id-column", DATASTORE_ID_COL);
        _elems.put("delimited-identifiers", DELIMITED_IDS);
        _elems.put("discriminator-column", DISCRIM_COL);
        _elems.put("discriminator-value", DISCRIM_VAL);
        _elems.put("entity-result", ENTITY_RESULT);
        _elems.put("enumerated", ENUMERATED);
        _elems.put("field-result", FIELD_RESULT);
        _elems.put("foreign-key", FK);
        _elems.put("fk_column-names", FK_COL_NAMES);
        _elems.put("fk_column_name", FK_COL_NAME);
        _elems.put("inheritance", INHERITANCE);
        _elems.put("index", INDEX);
        _elems.put("join-column", JOIN_COL);
        _elems.put("inverse-join-column", COL);
        _elems.put("join-table", JOIN_TABLE);
        _elems.put("map-key-enumerated", MAP_KEY_ENUMERATED);
        _elems.put("map-key-column", MAP_KEY_COL);
        _elems.put("map-key-join-column", MAP_KEY_JOIN_COL);
        _elems.put("map-key-temporal", MAP_KEY_TEMPORAL);
        _elems.put("name", NAME);
        _elems.put("order-column", ORDER_COLUMN);
        _elems.put("primary-key-join-column", PK_JOIN_COL);
        _elems.put("secondary-table", SECONDARY_TABLE);
        _elems.put("sql-result-set-mapping", SQL_RESULT_SET_MAPPING);
        _elems.put("table", TABLE);
        _elems.put("table-generator", TABLE_GEN);
        _elems.put("temporal", TEMPORAL);
        _elems.put("unique-constraint", UNIQUE);
        _elems.put("version-columns", VERSION_COLS);
        _elems.put("version-column", VERSION_COL);
    }

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

    private String _override = null;
    private String _schema = null;
    private String _colTable = null;
    private String _secondaryTable = null;
    private List<Column> _cols = null;
    private List<Column> _joinCols = null;
    private List<Column> _supJoinCols = null;
    private boolean _lob = false;
    private TemporalType _temporal = null;
    private EnumSet<UniqueFlag> _unique = EnumSet.noneOf(UniqueFlag.class);
    private DiscriminatorType _discType;
    private Column _discCol;
    private int _resultIdx = 0;
    private final DBDictionary _dict;

    // ForeignKey info
    private Attributes _foreignKeyAttributes = null;
    private List<String> _columnNamesList = null;
    private String[] _columnNames = {};

    private List<Column> _versionColumnsList = null;

    private final Map<Class<?>, ArrayList<DeferredEmbeddableOverrides>>
        _deferredMappings = new HashMap<>();

    /**
     * Constructor; supply configuration.
     */
    public XMLPersistenceMappingParser(JDBCConfiguration conf) {
        super(conf);
        _dict = conf.getDBDictionaryInstance();
    }

    @Override
    protected void reset() {
        super.reset();
        clearColumnInfo();
        clearClassInfo();
        clearSecondaryTableInfo();
        _override = null;
        _schema = null;
        _resultIdx = 0;
    }

    @Override
    protected Object startSystemMappingElement(String name, Attributes attrs)
        throws SAXException {
        MappingTag tag = _elems.get(name);
        if (tag == null) {
            if ("schema".equals(name))
                return name;
            return null;
        }

        boolean ret;
        switch (tag) {
            case TABLE_GEN:
                ret = startTableGenerator(attrs);
                break;
            case SQL_RESULT_SET_MAPPING:
                ret = startSQLResultSetMapping(attrs);
                break;
            case ENTITY_RESULT:
                ret = startEntityResult(attrs);
                break;
            case FIELD_RESULT:
                ret = startFieldResult(attrs);
                break;
            case COLUMN_RESULT:
                ret = startColumnResult(attrs);
                break;
            default:
                ret = false;
        }
        return (ret) ? tag : null;
    }

    @Override
    protected void endSystemMappingElement(String name)
        throws SAXException {
        MappingTag tag = _elems.get(name);
        if (tag == null) {
            if ("schema".equals(name)) {
                _schema = currentText();
                getRepository().getMetaDataFactory().getDefaults().setDefaultSchema(_schema);
            }
            return;
        }

        switch (tag) {
            case SQL_RESULT_SET_MAPPING:
                endSQLResultSetMapping();
                break;
            case ENTITY_RESULT:
                endEntityResult();
                break;
        }
    }

    @Override
    protected Object startClassMappingElement(String name, Attributes attrs)
        throws SAXException {
        MappingTag tag = _elems.get(name);
        if (tag == null)
            return null;

        boolean ret;
        switch (tag) {
            case TABLE:
                ret = startTable(attrs);
                break;
            case SECONDARY_TABLE:
                ret = startSecondaryTable(attrs);
                break;
            case DISCRIM_COL:
                parseDiscriminatorColumn(attrs);
                _discCol = parseColumn(attrs);
                ret = true;
                break;
            case DISCRIM_VAL:
                ret = true;
                break;
            case INHERITANCE:
                ret = startInheritance(attrs);
                break;
            case ASSOC_OVERRIDE:
            case ATTR_OVERRIDE:
                ret = startAttributeOverride(attrs);
                break;
            case PK_JOIN_COL:
                ret = startPrimaryKeyJoinColumn(attrs);
                break;
            case COL:
                ret = startColumn(attrs);
                break;
            case COLS:
                ret = true;
                break;
            case JOIN_COL:
                ret = startJoinColumn(attrs);
                break;
            case JOIN_TABLE:
                ret = startJoinTable(attrs);
                break;
            case TABLE_GEN:
                ret = startTableGenerator(attrs);
                break;
            case UNIQUE:
                ret = startUniqueConstraint(attrs);
                break;
            case NAME:
                ret = true;
                break;
            case TEMPORAL:
            case ENUMERATED:
            case MAP_KEY_ENUMERATED:
            case MAP_KEY_TEMPORAL:
                ret = true;
                break;
            case SQL_RESULT_SET_MAPPING:
                ret = startSQLResultSetMapping(attrs);
                break;
            case ENTITY_RESULT:
                ret = startEntityResult(attrs);
                break;
            case FIELD_RESULT:
                ret = startFieldResult(attrs);
                break;
            case COLUMN_RESULT:
                ret = startColumnResult(attrs);
                break;
            case COLUMN_NAME:
                ret = true;
                break;
            case COLLECTION_TABLE:
                ret = startCollectionTable(attrs);
                break;
            case MAP_KEY_COL:
                ret = startMapKeyColumn(attrs);
                break;
            case MAP_KEY_JOIN_COL:
                ret = startMapKeyJoinColumn(attrs);
                break;
            case DATASTORE_ID_COL:
                ret = startDatastoreIdCol(attrs);
                break;
            case INDEX:
                ret = startIndex(attrs);
                break;
            case FK:
                ret = startForeignKey(attrs);
                break;
            case FK_COL_NAMES:
                ret = startFKColumnNames(attrs);
                break;
            case FK_COL_NAME:
                ret = true;
                break;
            case VERSION_COLS:
                ret = startVersionColumns(attrs);
                break;
            case VERSION_COL:
                ret = startVersionColumn(attrs);
                break;
            default:
                ret = false;
        }
        return (ret) ? tag : null;
    }

    private boolean endName() {
        String name = this.currentText();
        if (StringUtil.isNotEmpty(name)) {
            Object current = currentElement();
            if (current instanceof Unique) {
                Unique unq = (Unique)current;
                unq.setIdentifier(DBIdentifier.newConstraint(name, delimit()));
            }
        }

        return true;
    }

    @Override
    protected void endClassMappingElement(String name)
        throws SAXException {
        MappingTag tag = _elems.get(name);
        if (tag == null)
            return;

        switch (tag) {
            case SECONDARY_TABLE:
                endSecondaryTable();
                break;
            case DISCRIM_VAL:
                endDiscriminatorValue();
                break;
            case ASSOC_OVERRIDE:
            case ATTR_OVERRIDE:
                endAttributeOverride();
                break;
            case JOIN_TABLE:
                endJoinTable();
                break;
            case TEMPORAL:
                endTemporal();
                break;
            case MAP_KEY_TEMPORAL:
                endMapKeyTemporal();
                break;
            case ENUMERATED:
                endEnumerated();
                break;
            case MAP_KEY_ENUMERATED:
                endMapKeyEnumerated();
                break;
            case SQL_RESULT_SET_MAPPING:
                endSQLResultSetMapping();
                break;
            case ENTITY_RESULT:
                endEntityResult();
                break;
            case UNIQUE:
                endUniqueConstraint();
                break;
            case COLUMN_NAME:
                endColumnName();
                break;
            case TABLE_GEN:
            	endTableGenerator();
            	break;
            case NAME:
                endName();
                break;
            case FK:
                endForeignKey();
                break;
            case FK_COL_NAMES:
                endFKColumnNames();
                break;
            case FK_COL_NAME:
                endFKColumnName();
                break;
            case VERSION_COLS:
                endVersionColumns();
                break;
        }
    }

    @Override
    protected void startClassMapping(ClassMetaData meta, boolean mappedSuper,
        Attributes attrs)
        throws SAXException {
        if (mappedSuper)
            ((ClassMapping) meta).getMappingInfo().setStrategy
                (NoneClassStrategy.ALIAS);
    }

    @Override
    protected void endClassMapping(ClassMetaData meta)
        throws SAXException {
        ClassMapping cm = (ClassMapping) meta;
        if (_schema != null)
            cm.getMappingInfo().setSchemaIdentifier(DBIdentifier.newSchema(_schema, delimit()));

        if (_supJoinCols != null)
            cm.getMappingInfo().setColumns(_supJoinCols);

        if (_discCol != null) {
            DiscriminatorMappingInfo dinfo = cm.getDiscriminator()
                    .getMappingInfo();
            switch (_discType) {
                case CHAR:
                    _discCol.setJavaType(JavaTypes.CHAR);
                    cm.getDiscriminator().setJavaType(JavaTypes.CHAR);
                    break;
                case INTEGER:
                    _discCol.setJavaType(JavaTypes.INT);
                    cm.getDiscriminator().setJavaType(JavaTypes.INT);
                    break;
                default:
                    _discCol.setJavaType(JavaTypes.STRING);
                    cm.getDiscriminator().setJavaType(JavaTypes.STRING);
                    break;
            }
            dinfo.setColumns(Arrays.asList(new Column[]{ _discCol }));
        }
        clearClassInfo();
    }

    /**
     * Clear cached class mapping info.
     */
    private void clearClassInfo() {
        _supJoinCols = null;
        _discCol = null;
        _discType = null;
    }

    /**
     * Start tracking secondary table information and columns
     */
    private boolean startSecondaryTable(Attributes attrs)
        throws SAXException {
        _secondaryTable = toTableIdentifier(attrs.getValue("schema"),
            attrs.getValue("name")).getName();
        ((ClassMapping)currentElement()).getMappingInfo()
        	.addSecondaryTable(DBIdentifier.newTable(_secondaryTable));
        return true;
    }

    /**
     * Set the secondary table information back to the owning class mapping.
     */
    private void endSecondaryTable() {
        ClassMapping cm = (ClassMapping) currentElement();
        ClassMappingInfo info = cm.getMappingInfo();
        info.setSecondaryTableJoinColumns(DBIdentifier.newTable(_secondaryTable, delimit()), _joinCols);
        clearSecondaryTableInfo();
    }

    /**
     * Clear cached secondary table info.
     */
    private void clearSecondaryTableInfo() {
        _joinCols = null;
        _secondaryTable = null;
    }

    /**
     * Parse table-generator.
     */
    private boolean startTableGenerator(Attributes attrs) {
        String name = attrs.getValue("name");
        Log log = getLog();
        if (log.isTraceEnabled())
            log.trace(_loc.get("parse-gen", name));
        if (getRepository().getCachedSequenceMetaData(name) != null
            && log.isWarnEnabled())
            log.warn(_loc.get("override-gen", name));

        SequenceMapping seq = (SequenceMapping) getRepository().
            addSequenceMetaData(name);
        seq.setSequencePlugin(SequenceMapping.IMPL_VALUE_TABLE);
        seq.setTableIdentifier(toTableIdentifier(attrs.getValue("schema"),
            attrs.getValue("table")));
        seq.setPrimaryKeyColumnIdentifier(DBIdentifier.newColumn(attrs.getValue("pk-column-name"), delimit()));
        seq.setSequenceColumnIdentifier(DBIdentifier.newColumn(attrs.getValue("value-column-name"), delimit()));
        seq.setPrimaryKeyValue(attrs.getValue("pk-column-value"));
        String val = attrs.getValue("initial-value");
        if (val != null)
            seq.setInitialValue(Integer.parseInt(val));
        val = attrs.getValue("allocation-size");
        if (val != null)
            seq.setAllocate(Integer.parseInt(val));

        Object cur = currentElement();
        Object scope = (cur instanceof ClassMetaData)
            ? ((ClassMetaData) cur).getDescribedType() : null;
        seq.setSource(getSourceFile(), scope, SourceTracker.SRC_XML);
        Locator locator = getLocation().getLocator();
        if (locator != null) {
            seq.setLineNumber(locator.getLineNumber());
            seq.setColNumber(locator.getColumnNumber());
        }
        pushElement(seq);
        return true;
    }

    private void endTableGenerator() {
    	popElement();
    }

    /**
     * Parse inheritance.
     */
    private boolean startInheritance(Attributes attrs) {
        String val = attrs.getValue("strategy");
        if (val == null)
            return true;

        ClassMapping cm = (ClassMapping) currentElement();
        ClassMappingInfo info = cm.getMappingInfo();
        switch (Enum.valueOf(InheritanceType.class, val)) {
            case SINGLE_TABLE:
                info.setHierarchyStrategy(FlatClassStrategy.ALIAS);
                break;
            case JOINED:
                info.setHierarchyStrategy(VerticalClassStrategy.ALIAS);
                break;
            case TABLE_PER_CLASS:
                info.setHierarchyStrategy(FullClassStrategy.ALIAS);
                break;
        }
        return true;
    }

    /**
     * Parse discriminator-value.
     */
    private void endDiscriminatorValue() {
        String val = currentText();
        if (StringUtil.isEmpty(val))
            return;

        ClassMapping cm = (ClassMapping) currentElement();
        cm.getDiscriminator().getMappingInfo().setValue(val);

        if (Modifier.isAbstract(cm.getDescribedType().getModifiers())
                && getLog().isInfoEnabled()) {
            getLog().info(
                    _loc.get("discriminator-on-abstract-class", cm
                            .getDescribedType().getName()));
        }
    }

    /**
     * Parse temporal.
     */
    private void endTemporal() {
        String temp = currentText();
        if (!StringUtil.isEmpty(temp))
            _temporal = Enum.valueOf(TemporalType.class, temp);
    }

    /**
     * Parse temporal.
     */
    private void endMapKeyTemporal() {
        String temp = currentText();
        TemporalType _mapKeyTemporal = null;
        if (!StringUtil.isEmpty(temp))
            _mapKeyTemporal = Enum.valueOf(TemporalType.class, temp);
        FieldMapping fm = (FieldMapping) currentElement();
        List<Column> cols = fm.getKeyMapping().getValueInfo().getColumns();
        if (cols.isEmpty()) {
            cols = Arrays.asList(new Column[]{ new Column() });
            fm.getKeyMapping().getValueInfo().setColumns(cols);
        }

        Column col = (Column) cols.get(0);
        switch (_mapKeyTemporal) {
            case DATE:
                col.setType(Types.DATE);
                break;
            case TIME:
                col.setType(Types.TIME);
                break;
            case TIMESTAMP:
                col.setType(Types.TIMESTAMP);
                break;
        }
    }

    /**
     * Parse enumerated.
     */
    private void endEnumerated() {
        String text = currentText();
        if (StringUtil.isEmpty(text))
            return;
        EnumType type = Enum.valueOf(EnumType.class, text);

        FieldMapping fm = (FieldMapping) currentElement();
        String strat = EnumValueHandler.class.getName() + "(StoreOrdinal="
            + (type == EnumType.ORDINAL) + ")";
        if (fm.isElementCollection())
            fm.getElementMapping().getValueInfo().setStrategy(strat);
        else
            fm.getValueInfo().setStrategy(strat);
    }

    /**
     * Parse map-key-enumerated.
     */
    private void endMapKeyEnumerated() {
        String text = currentText();
        if (StringUtil.isEmpty(text))
            return;
        EnumType type = Enum.valueOf(EnumType.class, text);

        FieldMapping fm = (FieldMapping) currentElement();
        String strat = EnumValueHandler.class.getName() + "(StoreOrdinal="
            + (type == EnumType.ORDINAL) + ")";
        fm.getKeyMapping().getValueInfo().setStrategy(strat);
    }

    @Override
    protected boolean startLob(Attributes attrs)
        throws SAXException {
        if (super.startLob(attrs)) {
            _lob = true;
            return true;
        }
        return false;
    }

    /**
     * Extend to clear annotation mapping info.
     */
    @Override
    protected void startFieldMapping(FieldMetaData field, Attributes attrs)
        throws SAXException {
        super.startFieldMapping(field, attrs);
        if (getAnnotationParser() != null) {
            FieldMapping fm = (FieldMapping) field;
            fm.getMappingInfo().clear();
            fm.getValueInfo().clear();
            fm.getElementMapping().getValueInfo().clear();
            fm.getKeyMapping().getValueInfo().clear();
        }
    }

    /**
     * Extend to set the columns.
     */
    @Override
    protected void endFieldMapping(FieldMetaData field)
        throws SAXException {
        // setup columns with cached lob and temporal info
        FieldMapping fm = (FieldMapping) field;
        if (_lob || _temporal != null) {
            int typeCode = fm.isElementCollection() ? fm.getElement().getDeclaredTypeCode() :
                fm.getDeclaredTypeCode();
            Class<?> type = fm.isElementCollection() ? fm.getElement().getDeclaredType() : fm.getDeclaredType();
            if (_cols == null) {
                _cols = new ArrayList<>(1);
                _cols.add(new Column());
            }
            for (Column col : _cols) {
                if (_lob && (typeCode == JavaTypes.STRING
                    || type == char[].class
                    || type == Character[].class)) {
                    col.setSize(-1);
                    col.setType(Types.CLOB);
                } else if (_lob)
                    col.setType(Types.BLOB);
                else {
                    switch (_temporal) {
                        case DATE:
                            col.setType(Types.DATE);
                            break;
                        case TIME:
                            col.setType(Types.TIME);
                            break;
                        case TIMESTAMP:
                            col.setType(Types.TIMESTAMP);
                            break;
                    }
                }
            }
        }

        if (_cols != null) {
            switch (fm.getDeclaredTypeCode()) {
                case JavaTypes.ARRAY:
                    Class<?> type = fm.getDeclaredType();
                    if (type == byte[].class || type == Byte[].class
                        || type == char[].class || type == Character[].class ) {
                        fm.getValueInfo().setColumns(_cols);
                        break;
                    }
                    // else no break
                case JavaTypes.COLLECTION:
                    if (!fm.getValue().isSerialized()) {
                        fm.getElementMapping().getValueInfo().setColumns(_cols);
                    } else  {
                        fm.getValueInfo().setColumns(_cols);
                    }
                    break;
                case JavaTypes.MAP:
                    fm.getElementMapping().getValueInfo().setColumns(_cols);
                    break;
                default:
                    fm.getValueInfo().setColumns(_cols);
            }
            if (_colTable != null)
                fm.getMappingInfo().setTableIdentifier(DBIdentifier.newTable(_colTable, delimit()));
            setUnique(fm);
        }
        clearColumnInfo();
    }

    /**
     * Set unique for field.
     */
    private void setUnique(FieldMapping fm) {
        setUnique(fm, _unique);
    }

    private void setUnique(FieldMapping fm, EnumSet<UniqueFlag> unique) {
        if (unique.size() == 2) // i.e. TRUE & FALSE
            getLog().warn(_loc.get("inconsist-col-attrs", fm));
        else if (unique.contains(UniqueFlag.TRUE))
            fm.getValueInfo().setUnique(new Unique());
    }

    /**
     * Clear field level column information.
     */
    private void clearColumnInfo() {
        _cols = null;
        _joinCols = null;
        _colTable = null;
        _lob = false;
        _temporal = null;
        _unique.clear();
    }

    /**
     * Parse attribute-override.
     */
    private boolean startAttributeOverride(Attributes attr) {
        _override = attr.getValue("name");
        return true;
    }

    /**
     * Set attribute override into proper mapping.
     */
    private void endAttributeOverride()
        throws SAXException {
        Object elem = currentElement();
        FieldMapping fm = null;
        if (elem instanceof ClassMapping)
            fm = getAttributeOverride((ClassMapping) elem);
        else {
            FieldMapping basefm = (FieldMapping) elem;

            fm = getAttributeOverrideForEmbeddable(basefm, _override, false);
            if (fm == null) {
                DeferredEmbeddableOverrides dfm =
                    getDeferredFieldMappingInfo(
                        AnnotationPersistenceMappingParser.
                        getEmbeddedClassType(basefm, _override),
                        basefm, _override, true);
                dfm._defCols = _cols;
                dfm._defTable = DBIdentifier.newTable(_colTable, delimit());
                dfm._attrName = _override;
                dfm._unique = _unique;
            }
        }
        if (fm != null && _cols != null) {
            fm.getValueInfo().setColumns(_cols);
            if (_colTable != null)
                fm.getMappingInfo().setTableIdentifier(DBIdentifier.newTable(_colTable, delimit()));
            setUnique(fm);
        }
        clearColumnInfo();
        _override = null;
    }

    /**
     * Return the proper override.
     */
    private FieldMapping getAttributeOverride(ClassMapping cm) {
        FieldMapping sup = (FieldMapping) cm.getDefinedSuperclassField
            (_override);
        if (sup == null)
            sup = (FieldMapping) cm.addDefinedSuperclassField(_override,
                Object.class, Object.class);
        return sup;
    }

    /**
     * Return the proper override.
     */
    private FieldMapping getAttributeOverrideForEmbeddable(FieldMapping fm,
        String attrName, boolean mustExist)
    throws SAXException {
        return AnnotationPersistenceMappingParser.getEmbeddedFieldMapping(fm,
            attrName, mustExist);
    }

    /**
     * Parse table.
     */
    private boolean startTable(Attributes attrs)
        throws SAXException {
        ClassMapping mapping = (ClassMapping) currentElement();
        if (mapping.isAbstract())
            throw new UserException(_loc.get("table-not-allowed", mapping));
        DBIdentifier table = toTableIdentifier(attrs.getValue("schema"),
            attrs.getValue("name"));
        if (!DBIdentifier.isNull(table))
            mapping.getMappingInfo().setTableIdentifier(table);
        return true;
    }

    /**
     * Parse join-table.
     */
    private boolean startJoinTable(Attributes attrs)
        throws SAXException {
        DBIdentifier sTable = toTableIdentifier(attrs.getValue("schema"),
            attrs.getValue("name"));
        if (!DBIdentifier.isNull(sTable)) {
            Object elem = currentElement();
            FieldMapping fm = null;
            if (elem instanceof FieldMapping) {
                fm = (FieldMapping) elem;
                if (_override != null) {
                    FieldMapping basefm = (FieldMapping) elem;
                    fm = getAttributeOverrideForEmbeddable(basefm,
                        _override, false);
                    if (fm == null) {
                        DeferredEmbeddableOverrides dfm =
                            getDeferredFieldMappingInfo(
                                AnnotationPersistenceMappingParser.
                                getEmbeddedClassType(basefm, _override),
                                basefm, _override, true);
                        dfm._defTable = sTable.clone();
                        dfm._attrName = _override;
                    }
                }
            } else if (elem instanceof ClassMapping) {
                ClassMapping cm = (ClassMapping) elem;
                fm = getAttributeOverride(cm);
            }
            if (fm != null)
                fm.getMappingInfo().setTableIdentifier(sTable);
        }
        return true;
    }

    /**
     * Set the join table information back.
     */
    private void endJoinTable() throws SAXException {
        Object elem = currentElement();
        FieldMapping fm = null;
        if (elem instanceof FieldMapping) {
            fm = (FieldMapping) elem;
            if (_override != null) {
                FieldMapping basefm = (FieldMapping) elem;
                fm = getAttributeOverrideForEmbeddable(basefm, _override,
                    false);
                if (fm == null) {
                    DeferredEmbeddableOverrides dfm =
                        getDeferredFieldMappingInfo(
                            AnnotationPersistenceMappingParser.
                            getEmbeddedClassType(basefm, _override),
                            basefm, _override, true);
                    dfm._defCols = _cols;
                    dfm._defElemJoinCols = _joinCols;
                    dfm._attrName = _override;
                }
            }
        } else if (elem instanceof ClassMapping){
            ClassMapping cm = (ClassMapping) elem;
            fm = getAttributeOverride(cm);
        }

        if (fm != null) {
            if (_joinCols != null)
                fm.getMappingInfo().setColumns(_joinCols);
            if (_cols != null)
                fm.getElementMapping().getValueInfo().setColumns(_cols);
        }
        clearColumnInfo();
    }

    /**
     * Parse primary-key-join-column.
     */
    private boolean startPrimaryKeyJoinColumn(Attributes attrs)
        throws SAXException {
        Column col = parseColumn(attrs);
        col.setFlag(Column.FLAG_PK_JOIN, true);
        // pk join columns on fields act as field cols
        if (currentElement() instanceof FieldMapping) {
            if (_cols == null)
                _cols = new ArrayList<>(3);
            _cols.add(col);
        } else if (currentParent() == SECONDARY_TABLE) {
            // pk join columns in secondary table acts as join cols
            if (_joinCols == null)
                _joinCols = new ArrayList<>(3);
            _joinCols.add(col);
        } else {
            // must be pk join cols from this class to superclass
            if (_supJoinCols == null)
                _supJoinCols = new ArrayList<>(3);
            _supJoinCols.add(col);
        }
        return true;
    }

    /**
     * Parse join-column.
     */
    private boolean startJoinColumn(Attributes attrs)
        throws SAXException {
        // only join cols in a join table join field table to class table;
        // others act as data fk cols
        Object currentParent = currentParent();
        if (currentParent == COLLECTION_TABLE) {
            FieldMapping fm = (FieldMapping) peekElement();
            Column col = parseColumn(attrs);
            List<Column> colList = fm.getMappingInfo().getColumns();
            if (colList.isEmpty()) {
                colList = new ArrayList<>();
                fm.getMappingInfo().setColumns(colList);
            }
            colList.add(col);
            fm.getMappingInfo().setColumns(colList);
            return true;
        }

        if (currentParent != JOIN_TABLE)
            return startColumn(attrs);

        if (_joinCols == null)
            _joinCols = new ArrayList<>(3);
        _joinCols.add(parseColumn(attrs));
        return true;
    }

    /**
     * Parse column.
     */
    private boolean startColumn(Attributes attrs)
        throws SAXException {
        Column col = parseColumn(attrs);
        Object obj = peekElement();
        if (obj instanceof FieldMapping) {
            FieldMapping fm = (FieldMapping)obj;
            // a collection of basic types
            // the column is in a separate table
            if (fm.isElementCollection() &&
                !fm.getElementMapping().isEmbedded()) {
                List<Column> list = fm.getElementMapping().getValueInfo().getColumns();
                if (list.size() == 0) {
                    list = new ArrayList<>();
                    fm.getElementMapping().getValueInfo().setColumns(list);
                }
                list.add(col);
                return true;
            }
        }
        if (_cols == null)
            _cols = new ArrayList<>(3);
        _cols.add(col);
        return true;
    }

    /**
     * Parse map-key-column.
     */
    private boolean startMapKeyColumn(Attributes attrs)
        throws SAXException {
        FieldMapping fm = (FieldMapping) peekElement();
        Column col = parseColumn(attrs);
        MappingInfo info = fm.getKeyMapping().getValueInfo();
        List<Column> cols = new ArrayList<>();
        cols.add(col);
        info.setColumns(cols);
        return true;
    }

    /**
     * Parse map-key-join-column.
     */
    private boolean startMapKeyJoinColumn(Attributes attrs)
    throws SAXException {
        boolean retVal = startMapKeyColumn(attrs);
        // check if name is not set, set it to default: the
        // concatenation of the name of the referencing property
        // or field name, "-", "KEY"
        FieldMapping fm = (FieldMapping) peekElement();
        MappingInfo info = fm.getKeyMapping().getValueInfo();
        List<Column> cols = info.getColumns();
        Column col = cols.get(0);
        if (DBIdentifier.isNull(col.getIdentifier())) {
            col.setIdentifier(DBIdentifier.newColumn(fm.getName() + "_" + "KEY", delimit()));
        }

        return retVal;
    }

    /**
     * Create a column with the given attributes.
     */
    private Column parseColumn(Attributes attrs)
        throws SAXException {
        Column col = new Column();
        String val = attrs.getValue("name");
        if (val != null)
            col.setIdentifier(DBIdentifier.newColumn(val, delimit()));
        val = attrs.getValue("referenced-column-name");
        if (val != null) {
            setTargetIdentifier(col, val);
        }
        val = attrs.getValue("column-definition");
        if (val != null)
            col.setTypeIdentifier(DBIdentifier.newColumnDefinition(val));
        val = attrs.getValue("precision");
        if (val != null)
            col.setSize(Integer.parseInt(val));
        val = attrs.getValue("length");
        if (val != null)
            col.setSize(Integer.parseInt(val));
        val = attrs.getValue("scale");
        if (val != null)
            col.setDecimalDigits(Integer.parseInt(val));
        val = attrs.getValue("nullable");
        if (val != null)
            col.setNotNull("false".equals(val));
        val = attrs.getValue("insertable");
        if (val != null)
            col.setFlag(Column.FLAG_UNINSERTABLE, "false".equals(val));
        val = attrs.getValue("updatable");
        if (val != null)
            col.setFlag(Column.FLAG_UNUPDATABLE, "false".equals(val));

        val = attrs.getValue("unique");
        if (val != null)
            _unique.add(Enum.valueOf(UniqueFlag.class, val.toUpperCase()));
        val = attrs.getValue("table");
        if (val != null) {
            if (_colTable != null && !_colTable.equals(val))
                throw getException(_loc.get("second-inconsist",
                    currentElement()));
            _colTable = val;
        }
        return col;
    }

    /**
     * Sets reference column name of the given column taking into account
     * that the given reference name that begins with a single quote represents
     * special meaning of a constant join column and hence not to be delimited.
     * @param col
     * @param refColumnName
     * @see <a href="http://issues.apache.org/jira/browse/OPENJPA-1979">OPENJPA-1979</a>
     */
    private static final char SINGLE_QUOTE = '\'';
    protected void setTargetIdentifier(Column col, String refColumnName) {
    	if (refColumnName.charAt(0) == SINGLE_QUOTE) {
    		col.setTargetIdentifier(DBIdentifier.newConstant(refColumnName));
    	} else {
    		col.setTargetIdentifier(DBIdentifier.newColumn(refColumnName, delimit()));
    	}
    }

    /**
     * Parse collectionTable.
     */
    private boolean startCollectionTable(Attributes attrs)
        throws SAXException {
        FieldMapping fm = (FieldMapping) peekElement();

        FieldMappingInfo info = fm.getMappingInfo();
        DBIdentifier ctbl = parseCollectionTable(attrs);
        info.setTableIdentifier(ctbl);
        return true;
    }

    private DBIdentifier parseCollectionTable(Attributes attrs) {
        String tVal = attrs.getValue("name");
        String sVal = attrs.getValue("schema");
        return toTableIdentifier(sVal, tVal);
    }

    /**
     * Form a qualified table name from a schema and table name.
     */
    private DBIdentifier toTableIdentifier(String schema, String table) {
        DBIdentifier sName = DBIdentifier.newSchema(schema, delimit());
        DBIdentifier tName = DBIdentifier.newTable(table, delimit());
        if (DBIdentifier.isEmpty(tName) || DBIdentifier.isEmpty(sName)) {
            return tName;
        }
        return QualifiedDBIdentifier.newPath(sName, tName);
    }


    /**
     * Start processing <code>sql-result-set-mapping</code> node.
     * Pushes the {@link QueryResultMapping} onto the stack as current element.
     */
    private boolean startSQLResultSetMapping(Attributes attrs) {
        String name = attrs.getValue("name");
        Log log = getLog();
        if (log.isTraceEnabled())
            log.trace(_loc.get("parse-sqlrsmapping", name));

        MappingRepository repos = (MappingRepository) getRepository();
        QueryResultMapping result = repos.getCachedQueryResultMapping
            (null, name);
        if (result != null && log.isWarnEnabled())
            log.warn(_loc.get("override-sqlrsmapping", name,
                currentLocation()));

        result = repos.addQueryResultMapping(null, name);
        result.setListingIndex(_resultIdx++);
        addComments(result);

        Object cur = currentElement();
        Object scope = (cur instanceof ClassMetaData)
            ? ((ClassMetaData) cur).getDescribedType() : null;
        result.setSource(getSourceFile(), scope, SourceTracker.SRC_XML);
        Locator locator = getLocation().getLocator();
        if (locator != null) {
            result.setLineNumber(locator.getLineNumber());
            result.setColNumber(locator.getColumnNumber());
        }
        pushElement(result);
        return true;
    }

    private void endSQLResultSetMapping()
        throws SAXException {
        popElement();
    }

    /**
     * Start processing <code>entity-result</code> node.
     * Pushes the {@link QueryResultMapping.PCResult}
     * onto the stack as current element.
     */
    private boolean startEntityResult(Attributes attrs)
        throws SAXException {
        Class<?> entityClass = classForName(attrs.getValue("entity-class"));
        String discriminator = DBIdentifier.newColumn(attrs.getValue("discriminator-column"), delimit()).getName();

        QueryResultMapping parent = (QueryResultMapping) currentElement();
        QueryResultMapping.PCResult result = parent.addPCResult(entityClass);
        if (!StringUtil.isEmpty(discriminator))
            result.addMapping(PCResult.DISCRIMINATOR, discriminator);
        pushElement(result);
        return true;
    }

    private void endEntityResult()
        throws SAXException {
        popElement();
    }

    /**
     * Process a <code>field-result</code> node.
     */
    private boolean startFieldResult(Attributes attrs)
        throws SAXException {
        String fieldName = attrs.getValue("name");
        String columnName = DBIdentifier.newColumn(attrs.getValue("column"), delimit()).getName();

        QueryResultMapping.PCResult parent = (QueryResultMapping.PCResult)
            currentElement();
        parent.addMapping(fieldName, columnName);
        return true;
    }

    /**
     * Process a <code>column-result</code> node.
     */
    private boolean startColumnResult(Attributes attrs)
        throws SAXException {
        QueryResultMapping parent = (QueryResultMapping) currentElement();
        parent.addColumnResult(attrs.getValue("name"));
        return true;
    }

    /**
     * Starts processing &lt;unique-constraint&gt; provided the tag occurs
     * within a ClassMapping element and <em>not</em> within a secondary
     * table.
     * Pushes the Unique element in the stack.
     */
    private boolean startUniqueConstraint(Attributes attrs)
        throws SAXException {
        Unique unique = new Unique();

        DBIdentifier name = DBIdentifier.newConstraint(attrs.getValue("name"), delimit());
        if (!DBIdentifier.isEmpty(name)) {
            unique.setIdentifier(name);
        }

        pushElement(unique);
        return true;
    }

    /**
     * Ends processing &lt;unique-constraint&gt; provided the tag occurs
     * within a ClassMapping element and <em>not</em> within a secondary
     * table. The stack is popped and the Unique element is added to the
     * ClassMappingInfo.
     */
    private void endUniqueConstraint() {
        Unique unique = (Unique) popElement();
        Object ctx = currentElement();
        DBIdentifier tableName = DBIdentifier.newTable("?");
        if (ctx instanceof ClassMapping) {
        	ClassMappingInfo info = ((ClassMapping) ctx).getMappingInfo();
        	tableName = (_secondaryTable == null)
        		? info.getTableIdentifier() : DBIdentifier.newTable(_secondaryTable, delimit());
        	info.addUnique(tableName, unique);
        } else if (ctx instanceof FieldMapping) {// JoinTable
        	FieldMappingInfo info = ((FieldMapping)ctx).getMappingInfo();
        	info.addJoinTableUnique(unique);
        } else if (ctx instanceof SequenceMapping) {
        	SequenceMapping seq = (SequenceMapping)ctx;
        	unique.setTableIdentifier(seq.getTableIdentifier());
        	Column[] uniqueColumns = unique.getColumns();
        	DBIdentifier[] columnNames = new DBIdentifier[uniqueColumns.length];
        	int i = 0;
        	for (Column uniqueColumn : uniqueColumns)
        		columnNames[i++] = uniqueColumn.getIdentifier().clone();
        	seq.setUniqueColumnsIdentifier(columnNames);
        	if (!DBIdentifier.isEmpty(unique.getIdentifier())) {
        	    seq.setUniqueConstraintIdentifier(unique.getIdentifier());
        	}
        } else {
        	throw new InternalException();
        }
    }

    /**
     * Ends processing &lt;column-name&gt; tag by adding the column name in
     * the current Unique element that resides in the top of the stack.
     */
    private boolean endColumnName() {
        Object current = currentElement();
        if (current instanceof Unique) {
            Unique unique = (Unique) current;
            Column column = new Column();
            column.setIdentifier(DBIdentifier.newColumn(this.currentText(), delimit()));
            unique.addColumn(column);
            return true;
        }
        return false;
    }

    /**
     * Track unique column settings.
	 */
	private static enum UniqueFlag
	{
		TRUE,
		FALSE
	}

	private void parseDiscriminatorColumn(Attributes attrs) {
	    String val = attrs.getValue("discriminator-type");
        if (val != null) {
            _discType = Enum.valueOf(DiscriminatorType.class, val);
        }
        else {
            _discType = DiscriminatorType.STRING;
        }

	}

    /**
     * Process OrderColumn.
     */
    @Override
    protected boolean startOrderColumn(Attributes attrs)
        throws SAXException {
        Column col = parseOrderColumn(attrs);
        Object obj = peekElement();
        if (obj instanceof FieldMapping) {
            FieldMapping fm = (FieldMapping)obj;
            fm.getMappingInfo().setOrderColumn(col);

        }
        return true;
    }
    /**
     * Create an order column with the given attributes.
     */
    private Column parseOrderColumn(Attributes attrs)
        throws SAXException {

        Column col = new Column();
        String val = attrs.getValue("name");
        if (val != null)
            col.setIdentifier(DBIdentifier.newColumn(val, delimit()));
        val = attrs.getValue("column-definition");
        if (val != null)
            col.setTypeIdentifier(DBIdentifier.newColumnDefinition(val));
        val = attrs.getValue("precision");
        if (val != null)
            col.setSize(Integer.parseInt(val));
        val = attrs.getValue("length");
        if (val != null)
            col.setSize(Integer.parseInt(val));
        val = attrs.getValue("scale");
        if (val != null)
            col.setDecimalDigits(Integer.parseInt(val));
        val = attrs.getValue("nullable");
        if (val != null)
            col.setNotNull("false".equals(val));
        val = attrs.getValue("insertable");
        if (val != null)
            col.setFlag(Column.FLAG_UNINSERTABLE, "false".equals(val));
        val = attrs.getValue("updatable");
        if (val != null)
            col.setFlag(Column.FLAG_UNUPDATABLE, "false".equals(val));

        return col;
    }

    /**
     * Process all deferred embeddable overrides for a given class.
     * This should only occur after the embeddable is mapped.
     *
     * @param embedType  embeddable class
     * @param access class level access for embeddable
     * @throws SAXException
     */
    @Override
    protected void applyDeferredEmbeddableOverrides(Class<?> cls)
        throws SAXException {
        ArrayList<DeferredEmbeddableOverrides> defMappings =
            _deferredMappings.get(cls);
        if (defMappings == null)
            return;

        for (DeferredEmbeddableOverrides defMap : defMappings) {
            FieldMapping fm = (FieldMapping)defMap._fm;
            if (defMap == null)
                return;
            fm = getAttributeOverrideForEmbeddable(fm, defMap._attrName, true);
            // Apply column, table, and unique overrides
            if (defMap._defCols != null) {
                fm.getValueInfo().setColumns(defMap._defCols);
                if (!DBIdentifier.isNull(defMap._defTable))
                    fm.getMappingInfo().setTableIdentifier(defMap._defTable);
                setUnique(fm, defMap._unique);
            }
            // Apply Join column and element join columns overrides overrides
            if (defMap._defJoinCols != null)
                fm.getMappingInfo().setColumns(defMap._defJoinCols);
            if (defMap._defElemJoinCols != null)
                fm.getElementMapping().getValueInfo().setColumns(
                    defMap._defElemJoinCols);
        }
        // Clean up after applying mappings
        defMappings.clear();
        _deferredMappings.remove(cls);
    }

    /*
     * Defer overrides for the specified field mapping
     */
    private void deferEmbeddableOverrides(
        Class<?> cls, DeferredEmbeddableOverrides defMap) {
        ArrayList<DeferredEmbeddableOverrides> defMappings =
                _deferredMappings.computeIfAbsent(cls, k -> new ArrayList<>());
        defMappings.add(defMap);
    }

    /*
     * Clean up any deferred mappings
     */
    @Override
    protected void clearDeferredMetaData() {
        super.clearDeferredMetaData();
        _deferredMappings.clear();
    }

    /*
     * Get embeddable overrides for the specified field mapping.  If create
     * is true, create a new override if one does not exist.
     */
    private DeferredEmbeddableOverrides
        getDeferredFieldMappingInfo(Class<?> cls, FieldMapping fm,
            String attrName, boolean create) {

        ArrayList<DeferredEmbeddableOverrides> defMappings =
            _deferredMappings.get(cls);

        if (defMappings == null && create) {
            defMappings = new ArrayList<>();
            _deferredMappings.put(cls, defMappings);
        }
        DeferredEmbeddableOverrides dfm =
            findDeferredMapping(cls, fm, attrName);

        if (dfm == null & create) {
            dfm = new DeferredEmbeddableOverrides(fm, attrName);
            deferEmbeddableOverrides(cls, dfm);
        }
        return dfm;
    }

    /*
     * Find deferred mappings for the given class, fm, and attr name
     */
    private DeferredEmbeddableOverrides findDeferredMapping(Class<?> cls,
        FieldMapping fm, String attrName) {
        ArrayList<DeferredEmbeddableOverrides> defMappings =
            _deferredMappings.get(cls);
        if (defMappings == null)
            return null;

        for (DeferredEmbeddableOverrides dfm : defMappings) {
            if (dfm != null && dfm._fm == fm &&
                attrName.equals(dfm._attrName))
                return dfm;
        }
        return null;
    }

    /**
     * Process all deferred embeddables using an unknown access type.
     */
    @Override
    protected void addDeferredEmbeddableMetaData() {
        super.addDeferredEmbeddableMetaData();
        if (_deferredMappings.size() > 0) {
            Set<Class<?>> keys = _deferredMappings.keySet();
            Class<?>[] classes = keys.toArray(new Class[keys.size()]);
            for (Class<?> aClass : classes) {
                try {
                    applyDeferredEmbeddableOverrides(aClass);
                }
                catch (Exception e) {
                    throw new MetaDataException(_loc.get("no-embeddable-metadata", aClass.getName()), e);
                }
            }
        }

    }

    // Inner class for storing override information
    class DeferredEmbeddableOverrides {
        DeferredEmbeddableOverrides(FieldMapping fm, String attrName) {
            _fm = fm;
            _attrName = attrName;
            _defTable = DBIdentifier.NULL;
        }
        private FieldMapping _fm;
        private List<Column> _defCols;
        private List<Column> _defElemJoinCols;
        private List<Column> _defJoinCols;
        private DBIdentifier _defTable;
        private String _attrName;
        private EnumSet<UniqueFlag> _unique;
    }

    @Override
    protected boolean startDelimitedIdentifiers() {
        JDBCConfiguration conf = (JDBCConfiguration) getConfiguration();
        DBDictionary dict = conf.getDBDictionaryInstance();
        dict.setDelimitIdentifiers(true);
        return true;
    }

    @Override
    protected String normalizeSequenceName(String seqName) {
        if (StringUtil.isEmpty(seqName)) {
            return seqName;
        }
        return DBIdentifier.newSequence(seqName, delimit()).getName();
    }

    @Override
    protected String normalizeSchemaName(String schName) {
        if (StringUtil.isEmpty(schName)) {
            return schName;
        }
        return DBIdentifier.newSchema(schName, delimit()).getName();
    }

    @Override
    protected String normalizeCatalogName(String catName) {
        if (StringUtil.isEmpty(catName)) {
            return catName;
        }
        return DBIdentifier.newCatalog(catName, delimit()).getName();
    }

    private boolean delimit() {
        return _dict.getDelimitIdentifiers();
    }

    /**
     * Translate the fetch mode enum value to the internal OpenJPA constant.
     */
    private static int toEagerFetchModeConstant(String mode) {
        if(mode.equals("NONE"))
            return EagerFetchModes.EAGER_NONE;
        else if (mode.equals("JOIN"))
            return EagerFetchModes.EAGER_JOIN;
        else if (mode.equals("PARALLEL"))
            return EagerFetchModes.EAGER_PARALLEL;
        else
            throw new InternalException();
    }

    private boolean startDatastoreIdCol(Attributes attrs)
        throws SAXException {

        ClassMapping cm = (ClassMapping) peekElement();

        Column col = new Column();
        String name = attrs.getValue("name");
        if (!StringUtil.isEmpty(name));
            col.setIdentifier(DBIdentifier.newColumn(name, delimit()));
        String columnDefinition= attrs.getValue("column-definition");
        if (!StringUtil.isEmpty(columnDefinition))
            col.setTypeIdentifier(DBIdentifier.newColumnDefinition(columnDefinition));
        int precision = Integer.parseInt(attrs.getValue("precision"));
        if (precision != 0)
            col.setSize(precision);
        col.setFlag(Column.FLAG_UNINSERTABLE, !Boolean.parseBoolean(attrs.getValue("insertable")));
        col.setFlag(Column.FLAG_UNUPDATABLE, !Boolean.parseBoolean(attrs.getValue("updatable")));
        cm.getMappingInfo().setColumns(Arrays.asList(new Column[]{ col }));

        return true;
    }

    private boolean startIndex(Attributes attrs)
        throws SAXException {

        FieldMapping fm = (FieldMapping) peekElement();

        parseIndex(fm.getValueInfo(),
            attrs.getValue("name"),
            Boolean.parseBoolean(attrs.getValue("enabled")),
            Boolean.parseBoolean(attrs.getValue("unique")));

        return true;
    }

    private void parseIndex(MappingInfo info, String name,
        boolean enabled, boolean unique) {
        if (!enabled) {
            info.setCanIndex(false);
            return;
        }

        org.apache.openjpa.jdbc.schema.Index idx =
            new org.apache.openjpa.jdbc.schema.Index();
        if (!StringUtil.isEmpty(name))
            idx.setIdentifier(DBIdentifier.newConstraint(name, delimit()));
        idx.setUnique(unique);
        info.setIndex(idx);
    }

    private boolean startForeignKey(Attributes attrs)
        throws SAXException {

        _foreignKeyAttributes = attrs;

        return true;
    }

    private void endForeignKey() {
        if (_foreignKeyAttributes == null) {
            throw new InternalException();
        }

        boolean implicit = Boolean.parseBoolean(_foreignKeyAttributes.getValue("implicit"));

        FieldMapping fm = (FieldMapping) peekElement();
        MappingInfo info = fm.getValueInfo();

        String name = _foreignKeyAttributes.getValue("name");
        boolean enabled = Boolean.parseBoolean(_foreignKeyAttributes.getValue("enabled"));
        boolean deferred = Boolean.parseBoolean(_foreignKeyAttributes.getValue("deferred"));
        boolean specified = Boolean.parseBoolean(_foreignKeyAttributes.getValue("specified"));
        String deleteActionString = _foreignKeyAttributes.getValue("delete-action");
        String updateActionString = _foreignKeyAttributes.getValue("update-action");
        int deleteAction = toForeignKeyInt(deleteActionString);
        int updateAction = toForeignKeyInt(updateActionString);

        if (!implicit) {
            parseForeignKey(info, name,
                enabled,
                deferred, deleteAction,
                updateAction);
        }
        else {
            info.setImplicitRelation(true);
            assertDefault(name, enabled, deferred, specified, updateAction, deleteAction);
        }

        _columnNamesList = null;
    }

    private void parseForeignKey(MappingInfo info, String name, boolean enabled,
        boolean deferred, int deleteAction, int updateAction) {

        if (!enabled) {
            info.setCanForeignKey(false);
            return;
        }

        org.apache.openjpa.jdbc.schema.ForeignKey fk =
            new org.apache.openjpa.jdbc.schema.ForeignKey();
        if (!StringUtil.isEmpty(name))
            fk.setIdentifier(DBIdentifier.newForeignKey(name, delimit()));
        fk.setDeferred(deferred);
        fk.setDeleteAction(deleteAction);
        fk.setUpdateAction(updateAction);
        info.setForeignKey(fk);

    }


    private int toForeignKeyInt(String action) {
        if (action.equals("RESTRICT")) {
            return org.apache.openjpa.jdbc.schema.ForeignKey.
                    ACTION_RESTRICT;
        }
        else if (action.equals("CASCADE")) {
            return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_CASCADE;
        }
        else if (action.equals("NULL")) {
            return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_NULL;
        }
        else if (action.equals("DEFAULT")) {
            return org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_DEFAULT;
        }
        else {
            throw new InternalException();
        }

    }

    private void assertDefault(String name, boolean enabled, boolean deferred, boolean specified,
        int updateAction, int deleteAction) {
        boolean isDefault = StringUtil.isEmpty(name)
            && enabled
            && !deferred
                && deleteAction == org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_RESTRICT
                && updateAction == org.apache.openjpa.jdbc.schema.ForeignKey.ACTION_RESTRICT
            && _columnNames.length == 0
            && specified;
        if (!isDefault)
            throw new UserException(_loc.get("implicit-non-default-fk", _cls,
                getSourceFile()).getMessage());
    }

    private boolean startFKColumnNames(Attributes attrs)
        throws SAXException {
        _columnNamesList = new ArrayList<>();
        return true;
    }

    private void endFKColumnNames() {
        if (_columnNamesList.size() > 0) {
            _columnNames = _columnNamesList.toArray(_columnNames);
            _columnNamesList.removeAll(_columnNamesList);
        }
    }

    private void endFKColumnName() {
        _columnNamesList.add(currentText());
    }

    private boolean startVersionColumns(Attributes attrs)
        throws SAXException {

        _versionColumnsList = new ArrayList<>();

        return true;
    }

    private void endVersionColumns() {
        if (_versionColumnsList == null) {
            throw new InternalException();
        }

        if (_versionColumnsList.size() > 0) {
            ClassMapping cm = (ClassMapping)peekElement();
            cm.getVersion().getMappingInfo().setColumns(_versionColumnsList);
            _versionColumnsList= null;
        }
    }

    private boolean startVersionColumn(Attributes attrs)
            throws SAXException {

        Column col = AnnotationPersistenceMappingParser.newColumn(attrs.getValue("name"),
            Boolean.parseBoolean(attrs.getValue("nullable")),
            Boolean.parseBoolean(attrs.getValue("insertable")),
            Boolean.parseBoolean(attrs.getValue("updatable")),
            attrs.getValue("columnDefinition"),
            Integer.parseInt(attrs.getValue("length")),
            Integer.parseInt(attrs.getValue("precision")),
            Integer.parseInt(attrs.getValue("scale")),
            attrs.getValue("table"),
            delimit());

        _versionColumnsList.add(col);

        return true;
        }

    @Override
    protected void parseEagerFetchModeAttr(FieldMetaData fmd, Attributes attrs)
        throws SAXException {

        FieldMapping fm = (FieldMapping) fmd;
        String eagerFetchMode = attrs.getValue("eager-fetch-mode");
        if (!StringUtil.isEmpty(eagerFetchMode)) {
            if (eagerFetchMode.equalsIgnoreCase("NONE")) {
                fm.setEagerFetchMode(EagerFetchModes.EAGER_NONE);
            } else if (eagerFetchMode.equalsIgnoreCase("JOIN")) {
                fm.setEagerFetchMode(EagerFetchModes.EAGER_JOIN);
            } else if (eagerFetchMode.equalsIgnoreCase("PARALLEL")) {
                fm.setEagerFetchMode(EagerFetchModes.EAGER_PARALLEL);
            }
        }
    }

    @Override
    protected void parseElementClassCriteriaAttr(FieldMetaData fmd, Attributes attrs)
        throws SAXException {

        String elementClassCriteriaString = attrs.getValue("element-class-criteria");
        if (!StringUtil.isEmpty(elementClassCriteriaString)) {
            FieldMapping fm = (FieldMapping) fmd;
            boolean elementClassCriteria = Boolean.parseBoolean(elementClassCriteriaString);
            fm.getElementMapping().getValueInfo().setUseClassCriteria(elementClassCriteria);
        }
    }

    @Override
    protected void parseStrategy(FieldMetaData fmd, Attributes attrs) {
        String strategy = attrs.getValue("strategy");
        if (!StringUtil.isEmpty(strategy)) {
            ((FieldMapping) fmd).getMappingInfo().setStrategy(strategy);
        }
    }

    @Override
    protected boolean startExtendedClass(String elem, Attributes attrs)
            throws SAXException {
        ClassMapping mapping = (ClassMapping) currentElement();

        String strategy = attrs.getValue("strategy");
        if (!StringUtil.isEmpty(strategy))
            mapping.getMappingInfo().setStrategy(strategy);

        String versionStrat = attrs.getValue("version-strategy");
        if (!StringUtil.isEmpty(versionStrat))
            mapping.getVersion().getMappingInfo().setStrategy(versionStrat);

        String discrimStrat = attrs.getValue("discriminator-strategy");
        if (!StringUtil.isEmpty(discrimStrat))
            mapping.getDiscriminator().getMappingInfo().setStrategy(discrimStrat);

        String subclassFetchMode = attrs.getValue("subclass-fetch-mode");
        if (!StringUtil.isEmpty(subclassFetchMode))
            mapping.setSubclassFetchMode(toEagerFetchModeConstant(subclassFetchMode));

        return true;
    }
}
