/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
// dmccann - June 17/2009 - 2.0 - Initial implementation
// Martin Vojtek - July 8/2014 - 2.6 - XmlNullPolicy and XmlElementNillable
package org.eclipse.persistence.jaxb.compiler;

import static org.eclipse.persistence.jaxb.javamodel.Helper.getQualifiedJavaTypeName;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;

import jakarta.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaField;
import org.eclipse.persistence.jaxb.javamodel.JavaHasAnnotations;
import org.eclipse.persistence.jaxb.javamodel.JavaMethod;
import org.eclipse.persistence.jaxb.javamodel.JavaModelInput;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl;
import org.eclipse.persistence.jaxb.xmlmodel.JavaAttribute;
import org.eclipse.persistence.jaxb.xmlmodel.JavaType;
import org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAbstractNullPolicy;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAnyAttribute;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAnyElement;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAttribute;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlEnums;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.XmlRegistries;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElement;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementNillable;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementRefs;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper;
import org.eclipse.persistence.jaxb.xmlmodel.XmlElements;
import org.eclipse.persistence.jaxb.xmlmodel.XmlEnum;
import org.eclipse.persistence.jaxb.xmlmodel.XmlEnumValue;
import org.eclipse.persistence.jaxb.xmlmodel.XmlInverseReference;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapters;
import org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes;
import org.eclipse.persistence.jaxb.xmlmodel.XmlMap;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNamedObjectGraph;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNsForm;
import org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy;
import org.eclipse.persistence.jaxb.xmlmodel.XmlProperties.XmlProperty;
import org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchema.XmlNs;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaType;
import org.eclipse.persistence.jaxb.xmlmodel.XmlSchemaTypes;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransient;
import org.eclipse.persistence.jaxb.xmlmodel.XmlValue;
import org.eclipse.persistence.jaxb.xmlmodel.XmlVariableNode;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLNameTransformer;

/**
 * INTERNAL:
 * <p>
 * Purpose: XMLProcessor is used to process the meta data provided
 * in external OXM XML files.  This information is then used in conjunction with the
 * information from AnnotationsProcess to generate schemas (via SchemaGenerator)
 * and mappings (via MappingsGenerator).
 * </p>
 *
 * <p>
 * As a general rule meta data provided in external OXM XML files overrides meta data
 * specified through annotations.
 * </p>
 * @see org.eclipse.persistence.jaxb.compiler.Generator
 */
public class XMLProcessor {
    private Map<String, XmlBindings> xmlBindingMap;
    private JavaModelInput jModelInput;
    private AnnotationsProcessor aProcessor;
    private JAXBMetadataLogger logger;
    private static final char COLON = ':';
    private static final char SLASH = '/';
    private static final String SELF = ".";
    private static final char OPEN_BRACKET =  '[';
    private static final String IS_STR = "is";
    private static final String GET_STR = "get";
    private static final String SET_STR = "set";
    private static final String JAVA_LANG_OBJECT = "java.lang.Object";
    public static final String DEFAULT = "##default";
    public static final String GENERATE = "##generate";


    /**
     * This is the preferred constructor.
     *
     * @param bindings
     */
    public XMLProcessor(Map<String, XmlBindings> bindings) {
        this.xmlBindingMap = bindings;
    }

    /**
     * Process XmlBindings on a per package basis for a given
     * AnnotationsProcessor instance.
     *
     * @param annotationsProcessor
     */
    public void processXML(AnnotationsProcessor annotationsProcessor, JavaModelInput jModelInput, TypeMappingInfo[] typeMappingInfos, JavaClass[] originalJavaClasses) {
        this.jModelInput = jModelInput;
        this.aProcessor = annotationsProcessor;
        this.aProcessor.setHasXmlBindings(true);
        Map<String, XmlEnum> xmlEnumMap = new HashMap<String, XmlEnum>();
        aProcessor.init(originalJavaClasses, typeMappingInfos);

        // build a map of packages to JavaClass so we only process the
        // JavaClasses for a given package additional classes - i.e. ones from
        // packages not listed in XML - will be processed later
        Map<String, ArrayList<JavaClass>> pkgToClassMap = buildPackageToJavaClassMap();

        // process each XmlBindings in the map
        XmlBindings xmlBindings;
        for (String packageName : xmlBindingMap.keySet()) {
            ArrayList classesToProcess = pkgToClassMap.get(packageName);
            if (classesToProcess == null) {
                getLogger().logWarning("jaxb_metadata_warning_no_classes_to_process", new Object[] { packageName });
                continue;
            }

            xmlBindings = xmlBindingMap.get(packageName);

            // handle @XmlSchema override
            NamespaceInfo nsInfo = processXmlSchema(xmlBindings, packageName);
            if (nsInfo != null) {
                aProcessor.addPackageToNamespaceMapping(packageName, nsInfo);
            }

            // handle @XmlElementNillable override
            if (null != xmlBindings.getXmlElementNillable()) {
                aProcessor.addPackageToXmlElementNillable(packageName, xmlBindings.getXmlElementNillable());
            }

            // handle @XmlNullPolicy override
            if (null != xmlBindings.getXmlNullPolicy()) {
                aProcessor.addPackageToXmlNullPolicy(packageName, xmlBindings.getXmlNullPolicy());
            }

            // handle xml-registries
            // add an entry to the map of registries keyed on factory class name for each
            XmlRegistries xmlRegs = xmlBindings.getXmlRegistries();
            if (xmlRegs != null) {
                for (XmlRegistry xmlReg : xmlRegs.getXmlRegistry()) {
                    aProcessor.addXmlRegistry(xmlReg.getName(), xmlReg);
                }
            }

            // build an array of JavaModel classes to process
            JavaClass[] javaClasses = (JavaClass[]) classesToProcess.toArray(new JavaClass[classesToProcess.size()]);

            // handle xml-enums
            // build a map of enum class names to XmlEnum objects
            XmlEnums xmlEnums = xmlBindings.getXmlEnums();
            if (xmlEnums != null) {
                for (XmlEnum xmlEnum : xmlEnums.getXmlEnum()) {
                    xmlEnumMap.put(getQualifiedJavaTypeName(xmlEnum.getJavaEnum(), packageName), xmlEnum);
                }
            }

            //handle superclass override
            if(xmlBindings.getJavaTypes() != null) {
                List<JavaType> types = xmlBindings.getJavaTypes().getJavaType();
                for(JavaType next:types) {
                    JavaClass typeClass = jModelInput.getJavaModel().getClass(getQualifiedJavaTypeName(next.getName(), packageName));
                    if(typeClass != null && typeClass.getClass() == JavaClassImpl.class) {
                        if(next.getSuperType() != null && !(next.getSuperType().equals(DEFAULT))) {
                            JavaClass newSuperClass = jModelInput.getJavaModel().getClass(next.getSuperType());
                            ((JavaClassImpl)typeClass).setSuperClassOverride(newSuperClass);
                        }
                    }
                }
            }
            // pre-build the TypeInfo objects
            Map<String, TypeInfo> typeInfoMap = aProcessor.preBuildTypeInfo(javaClasses);

            // handle package-level xml-schema-types
            List<XmlSchemaType> xmlSchemaTypes = null;
            XmlSchemaTypes sTypes = xmlBindings.getXmlSchemaTypes();
            if (sTypes != null) {
                xmlSchemaTypes = sTypes.getXmlSchemaType();
            } else {
                xmlSchemaTypes = new ArrayList<XmlSchemaType>();
            }
            // handle package-level xml-schema-type
            if (xmlBindings.getXmlSchemaType() != null) {
                xmlSchemaTypes.add(xmlBindings.getXmlSchemaType());
            }
            // process each xml-schema-type entry
            for (XmlSchemaType sType : xmlSchemaTypes) {
                JavaClass jClass = aProcessor.getHelper().getJavaClass(sType.getType());
                if (jClass != null) {
                    aProcessor.processSchemaType(sType.getName(), sType.getNamespace(), jClass.getQualifiedName());
                }
            }

            PackageInfo packageInfo = aProcessor.getPackageToPackageInfoMappings().get(packageName);
            if (packageInfo == null) {
                packageInfo = new PackageInfo();
            }
            if(xmlBindings.isSetXmlAccessorType()) {
                packageInfo.setAccessType(xmlBindings.getXmlAccessorType());
            }
            JavaTypes jTypes = xmlBindings.getJavaTypes();
            if (jTypes != null) {
                for (JavaType javaType : jTypes.getJavaType()) {
                    TypeInfo info = typeInfoMap.get(getQualifiedJavaTypeName(javaType.getName(), packageName));

                    // package/class override order:
                    // 1 - xml class-level
                    // 2 - java object class-level
                    // 3 - xml package-level
                    // 4 - package-info.java

                    // handle class-level @XmlJavaTypeAdapter override
                    if (javaType.getXmlJavaTypeAdapter() != null) {
                        info.setXmlJavaTypeAdapter(javaType.getXmlJavaTypeAdapter());
                    }

                    // handle class-level @XmlNullPolicy override
                    XmlNullPolicy xmlNullPolicy = javaType.getXmlNullPolicy();
                    if (null != xmlNullPolicy) {
                        info.setXmlNullPolicy(xmlNullPolicy);
                    }

                    // handle class-level @XmlElementNillable override
                    XmlElementNillable xmlElementNillable = javaType.getXmlElementNillable();
                    if (null != xmlElementNillable) {
                        info.setXmlElementNillable(xmlElementNillable.isNillable());
                    }

                    // handle class-level @XmlNameTransformer
                    String transformerClassName = javaType.getXmlNameTransformer();

                    XMLNameTransformer transformer = getXMLNameTransformerClassFromString(transformerClassName);
                    if(transformer != null){
                        info.setXmlNameTransformer(transformer);
                    }
                    // handle class-level @XmlExtensible override
                    if (javaType.getXmlVirtualAccessMethods() != null) {
                        info.setXmlVirtualAccessMethods(javaType.getXmlVirtualAccessMethods());
                    }

                    // handle class-level @XmlAccessorOrder override
                    if (javaType.isSetXmlAccessorOrder()) {
                        info.setXmlAccessOrder(javaType.getXmlAccessorOrder());
                    } else if (!info.isSetXmlAccessOrder()) {
                        // handle package-level @XmlAccessorOrder override
                        if (xmlBindings.isSetXmlAccessorOrder()) {
                            info.setXmlAccessOrder(xmlBindings.getXmlAccessorOrder());
                        } else {
                            // finally, check the NamespaceInfo
                            info.setXmlAccessOrder(packageInfo.getAccessOrder());
                        }
                    }

                    // handle class-level @XmlAccessorType override
                    if (javaType.isSetXmlAccessorType()) {
                        info.setXmlAccessType(javaType.getXmlAccessorType());
                    }
                    // handle @XmlInlineBinaryData override
                    if (javaType.isSetXmlInlineBinaryData()) {
                        info.setInlineBinaryData(javaType.isXmlInlineBinaryData());
                    }
                    // handle @XmlTransient override
                    if (javaType.isSetXmlTransient()) {
                        info.setXmlTransient(javaType.isXmlTransient());
                    }
                    // handle @XmlRootElement
                    if (javaType.getXmlRootElement() != null) {
                        info.setXmlRootElement(javaType.getXmlRootElement());
                    }
                    // handle @XmlSeeAlso override
                    if (javaType.getXmlSeeAlso() != null && javaType.getXmlSeeAlso().size() > 0) {
                        info.setXmlSeeAlso(javaType.getXmlSeeAlso());
                    }
                    // handle @XmlType override
                    if (javaType.getXmlType() != null) {
                        info.setXmlType(javaType.getXmlType());
                    }
                    // handle @XmlCustomizer override
                    if (javaType.getXmlCustomizer() != null) {
                        info.setXmlCustomizer(javaType.getXmlCustomizer());
                    }
                    // handle @XmlClassExtractor override
                    if (javaType.getXmlClassExtractor() != null) {
                        info.setClassExtractorName(javaType.getXmlClassExtractor().getClazz());
                    }
                    // handle @XmlProperties override
                    if (javaType.getXmlProperties() != null && javaType.getXmlProperties().getXmlProperty().size() > 0) {
                        // may need to merge with @XmlProperties (xml wins in the case of a conflict)
                        if (info.getUserProperties() != null) {
                            info.setUserProperties(mergeUserPropertyMap(javaType.getXmlProperties().getXmlProperty(), info.getUserProperties()));
                        } else {
                            info.setUserProperties(createUserPropertyMap(javaType.getXmlProperties().getXmlProperty()));
                        }
                    }
                    // handle @XmlDiscriminatorNode override
                    if (javaType.getXmlDiscriminatorNode() != null) {
                        info.setXmlDiscriminatorNode(javaType.getXmlDiscriminatorNode());
                    }
                    // handle @NamedObjectGraph/@NamedObjectGraphs override
                    if (javaType.getXmlNamedObjectGraphs() != null) {
                        List<XmlNamedObjectGraph> currentGraphs = info.getObjectGraphs();
                        for(XmlNamedObjectGraph nextGraph:javaType.getXmlNamedObjectGraphs().getXmlNamedObjectGraph()) {
                            //check to see if a graph with the same name already exists
                            //if so, remove it and replace it with the one from xml.
                            //if not, add the new one
                            for(XmlNamedObjectGraph nextExistingGraph: currentGraphs) {
                                if(nextGraph.getName().equals(nextExistingGraph.getName())) {
                                    currentGraphs.remove(nextExistingGraph);
                                    break;
                                }
                            }
                        }
                        currentGraphs.addAll(javaType.getXmlNamedObjectGraphs().getXmlNamedObjectGraph());
                    }
                    // handle @XmlDiscriminatorValue override
                    if (javaType.getXmlDiscriminatorValue() != null) {
                        info.setXmlDiscriminatorValue(javaType.getXmlDiscriminatorValue());
                    }
                }
            }
            //apply package-level @XmlNameTransformer
            Map<String, TypeInfo> typeInfos = aProcessor.getTypeInfosForPackage(packageName);
            String transformerClassName = xmlBindings.getXmlNameTransformer();

            XMLNameTransformer transformer = getXMLNameTransformerClassFromString(transformerClassName);
            if(transformer != null){
               packageInfo.setXmlNameTransformer(transformer);
            }
            // apply package-level @XmlJavaTypeAdapters
            for (TypeInfo tInfo : typeInfos.values()) {
                if(xmlBindings.getXmlJavaTypeAdapters() != null){
                    List<XmlJavaTypeAdapter> adapters = xmlBindings.getXmlJavaTypeAdapters().getXmlJavaTypeAdapter();
                    for (XmlJavaTypeAdapter xja : adapters) {
                        try {
                            JavaClass adapterClass = jModelInput.getJavaModel().getClass(xja.getValue());
                            JavaClass boundType = jModelInput.getJavaModel().getClass(xja.getType());
                            if (boundType != null) {
                                tInfo.addPackageLevelAdapterClass(adapterClass, boundType);
                                packageInfo.getPackageLevelAdaptersByClass().put(boundType.getQualifiedName(), adapterClass);
                            }
                        } catch(JAXBException e) {
                            throw JAXBException.invalidPackageAdapterClass(xja.getValue(), packageName);
                        }
                    }
                }
            }

        }
        for (String packageName : xmlBindingMap.keySet()) {
            ArrayList classesToProcess = pkgToClassMap.get(packageName);
            if (classesToProcess == null) {
                getLogger().logWarning("jaxb_metadata_warning_no_classes_to_process", new Object[] { packageName });
                continue;
            }

            xmlBindings = xmlBindingMap.get(packageName);
            JavaClass[] javaClasses = (JavaClass[]) classesToProcess.toArray(new JavaClass[classesToProcess.size()]);
            // post-build the TypeInfo objects
            javaClasses = aProcessor.postBuildTypeInfo(javaClasses);



            // get the generated TypeInfo
            Map<String, TypeInfo> typeInfosForPackage = aProcessor.getTypeInfosForPackage(packageName);

            // update xml-enum info if necessary
            for (Entry<String, TypeInfo> entry : typeInfosForPackage.entrySet()) {
                TypeInfo tInfo = entry.getValue();
                if (tInfo.isEnumerationType()) {
                    EnumTypeInfo etInfo = (EnumTypeInfo) tInfo;
                    XmlEnum xmlEnum = xmlEnumMap.get(etInfo.getClassName());
                    if (xmlEnum != null) {
                        JavaClass restrictionClass = aProcessor.getHelper().getJavaClass(xmlEnum.getValue());
                        // default to String if necessary
                        if (restrictionClass == null) {
                            restrictionClass = jModelInput.getJavaModel().getClass(String.class);
                        }
                        etInfo.setRestrictionBase(aProcessor.getSchemaTypeFor(restrictionClass));
                        for (XmlEnumValue xmlEnumValue : xmlEnum.getXmlEnumValue()) {
                            // overwrite any existing entries (from annotations)
                            etInfo.addJavaFieldToXmlEnumValuePair(true, xmlEnumValue.getJavaEnumValue(), xmlEnumValue.getValue());
                        }
                    }
                }
            }

            // update TypeInfo objects based on the JavaTypes
            JavaTypes jTypes = xmlBindings.getJavaTypes();
            if (jTypes != null) {
                PackageInfo packageInfo = aProcessor.getPackageToPackageInfoMappings().get(packageName);
                NamespaceInfo nsInfo = null;
                if(null != packageInfo) {
                    nsInfo = packageInfo.getNamespaceInfo();
                }
                for (JavaType javaType : jTypes.getJavaType()) {
                    processJavaType(javaType, typeInfosForPackage.get(getQualifiedJavaTypeName(javaType.getName(), packageName)), nsInfo);
                }
            }
            // remove the entry for this package from the map
            pkgToClassMap.remove(packageName);
        }

        // now process remaining classes
        Iterator<ArrayList<JavaClass>> classIt = pkgToClassMap.values().iterator();
        while (classIt.hasNext()) {
            ArrayList<JavaClass> jClassList = classIt.next();
            JavaClass[] jClassArray = jClassList.toArray(new JavaClass[jClassList.size()]);
            aProcessor.buildNewTypeInfo(jClassArray);
            aProcessor.checkForCallbackMethods();
        }

        // need to ensure that any bound types (from XmlJavaTypeAdapter) have TypeInfo
        // objects built for them - SchemaGenerator will require a descriptor for each
        Map<String, TypeInfo> typeInfos = (Map<String, TypeInfo>) ((HashMap)aProcessor.getTypeInfos()).clone();
        for (Entry<String, TypeInfo> entry : typeInfos.entrySet()) {
            JavaClass[] jClassArray;
            for (Property prop : entry.getValue().getPropertyList()) {
                if (prop.isSetXmlJavaTypeAdapter()) {
                    jClassArray = new JavaClass[] { prop.getActualType() };
                    aProcessor.buildNewTypeInfo(jClassArray);
                }
            }
        }

        // now trigger the annotations processor to process the classes
        List<JavaClass> jClasses = aProcessor.getTypeInfoClasses();

        // If multiple bindings (packages) are supplied, re-process super classes
        // (in case super and sub classes were in different packages)
        if (xmlBindingMap.size() > 1) {
            for (JavaClass c : jClasses) {
                TypeInfo ti = aProcessor.getTypeInfos().get(c.getQualifiedName());
                aProcessor.processPropertiesSuperClass(c, ti);
            }
        }

        aProcessor.processPropertyTypes(jClasses.toArray(new JavaClass[jClasses.size()]));
        aProcessor.finalizeProperties();
        aProcessor.createElementsForTypeMappingInfo();
        aProcessor.checkForCallbackMethods();
    }

    private XMLNameTransformer getXMLNameTransformerClassFromString(String transformerClassName){
    XMLNameTransformer transformer = null;
        if(transformerClassName != null){
           Class nameTransformerClass;

             try {
                 nameTransformerClass = Class.forName(transformerClassName);
             } catch (ClassNotFoundException ex) {
                 throw JAXBException.exceptionWithNameTransformerClass(transformerClassName, ex);
             }
             try {
                 transformer = (XMLNameTransformer) nameTransformerClass.getConstructor().newInstance();
             } catch (ReflectiveOperationException ex) {
                 throw JAXBException.exceptionWithNameTransformerClass(transformerClassName, ex);
             }
         }
         return transformer;

    }

    /**
     * Process a given JavaType's attributes.
     *
     * @param javaType
     * @param typeInfo
     * @param nsInfo
     */
    private void processJavaType(JavaType javaType, TypeInfo typeInfo, NamespaceInfo nsInfo) {
        // process field/property overrides
        if (null != javaType.getJavaAttributes()) {
            List<String> processedPropertyNames = new ArrayList<String>();
            for (JAXBElement jaxbElement : javaType.getJavaAttributes().getJavaAttribute()) {
                JavaAttribute javaAttribute = (JavaAttribute) jaxbElement.getValue();

                Property originalProperty = typeInfo.getOriginalProperties().get(javaAttribute.getJavaAttribute());
                if(javaAttribute.getXmlAccessorType() != null) {
                    originalProperty = processPropertyForAccessorType(typeInfo, javaAttribute, originalProperty);
                }
                if (originalProperty == null) {
                    if (typeInfo.getXmlVirtualAccessMethods() != null) {
                        Property newProperty = new Property(this.aProcessor.getHelper());
                        newProperty.setPropertyName(javaAttribute.getJavaAttribute());
                        newProperty.setExtension(true);

                        String attributeType = null;

                        if (javaAttribute instanceof XmlElement) {
                            attributeType = ((XmlElement) javaAttribute).getType();
                        } else if (javaAttribute instanceof XmlAttribute) {
                            attributeType = ((XmlAttribute) javaAttribute).getType();
                        }

                        if (attributeType != null && attributeType.equals("DEFAULT")) {
                            newProperty.setType(jModelInput.getJavaModel().getClass(attributeType));
                        } else {
                            newProperty.setType(jModelInput.getJavaModel().getClass(Helper.STRING));
                        }

                        originalProperty = newProperty;
                        typeInfo.addProperty(javaAttribute.getJavaAttribute(), newProperty);
                    } else {
                        getLogger().logWarning(JAXBMetadataLogger.NO_PROPERTY_FOR_JAVA_ATTRIBUTE, new Object[] { javaAttribute.getJavaAttribute(), javaType.getName() });
                        continue;
                    }
                }

                boolean alreadyProcessed = processedPropertyNames.contains(javaAttribute.getJavaAttribute());
                Property propToProcess;

                // In the case where there is more than one javaAttribute for the same Property
                // (multiple mappings to same attribute) clone the original and put it in a
                // separate Map; otherwise, update the property as per usual
                if (alreadyProcessed) {
                    propToProcess = (Property) originalProperty.clone();
                } else {
                    propToProcess = typeInfo.getProperties().get(javaAttribute.getJavaAttribute());
                }

                processJavaAttribute(typeInfo, javaAttribute, propToProcess, nsInfo, javaType);

                // (Bug 346081) if discover a transient attribute apply same behavior as transient annotation and remove
                if(propToProcess.isTransient()){
                    typeInfo.getPropertyList().remove(propToProcess);
                }

                // if we are dealing with multiple mappings for the same attribute, leave the existing
                // property as-is and update the additionalProperties list on the owning TypeInfo
                if (alreadyProcessed) {
                    List<Property> additionalProps = null;
                    if(typeInfo.hasAdditionalProperties()) {
                        additionalProps = typeInfo.getAdditionalProperties().get(javaAttribute.getJavaAttribute());
                    }
                    if (additionalProps == null) {
                        additionalProps = new ArrayList<Property>();
                    }
                    additionalProps.add(propToProcess);
                    typeInfo.getAdditionalProperties().put(javaAttribute.getJavaAttribute(), additionalProps);
                } else {
                    // single mapping case; update the TypeInfo as per usual
                    typeInfo.getProperties().put(javaAttribute.getJavaAttribute(), propToProcess);
                    // keep track of processed property names
                    processedPropertyNames.add(javaAttribute.getJavaAttribute());
                }
            }
        }
    }

    private Property processPropertyForAccessorType(TypeInfo typeInfo, JavaAttribute javaAttribute, Property originalProperty) {
        if(originalProperty == null) {
            Property prop = createProperty(typeInfo, javaAttribute);
            if(prop != null) {
                typeInfo.addProperty(prop.getPropertyName(), prop);
            }
            return prop;
        }

        if((javaAttribute.getXmlAccessorType() == XmlAccessType.FIELD && !(originalProperty.isMethodProperty())) ||
                javaAttribute.getXmlAccessorType() == XmlAccessType.PROPERTY && originalProperty.isMethodProperty()) {
            return originalProperty;
        }

        originalProperty.setMethodProperty(!(originalProperty.isMethodProperty()));
        if(originalProperty.isMethodProperty()) {
            //figure out get and set method names. See if they exist.
            JavaClass jClass = this.jModelInput.getJavaModel().getClass(typeInfo.getJavaClassName());

            String propName = originalProperty.getPropertyName();
            propName = Character.toUpperCase(propName.charAt(0)) + propName.substring(1);
            String getMethodName = GET_STR + propName;
            String setMethodName = SET_STR + propName;

            JavaMethod getMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{});
            if(getMethod == null) {
                getMethodName = IS_STR + propName;
                getMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{});
            }
            JavaMethod setMethod = jClass.getDeclaredMethod(setMethodName, new JavaClass[]{originalProperty.getType()});
            if(getMethod != null) {
                originalProperty.setGetMethodName(getMethodName);
            }
            if(setMethod != null) {
                originalProperty.setSetMethodName(setMethodName);
            }
        } else {
            originalProperty.setGetMethodName(null);
            originalProperty.setSetMethodName(null);
            originalProperty.setMethodProperty(false);
        }

        return originalProperty;
    }

    private Property createProperty(TypeInfo info, JavaAttribute javaAttribute) {
        XmlAccessType xmlAccessorType = javaAttribute.getXmlAccessorType();
        //Property prop = new Property();
        //prop.setPropertyName(javaAttribute.getJavaAttribute());
        String propName = javaAttribute.getJavaAttribute();
        JavaHasAnnotations element = null;
        JavaClass pType = null;
        JavaClass jClass = this.jModelInput.getJavaModel().getClass(info.getJavaClassName());
        if(xmlAccessorType == XmlAccessType.PROPERTY) {
            //set up accessor method names
            String name  = Character.toUpperCase(propName.charAt(0)) + propName.substring(1);
            String getMethodName = GET_STR + name;
            String setMethodName = SET_STR + name;

            JavaMethod jMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{});
            if(jMethod == null) {
                getMethodName = IS_STR + name;
                jMethod = jClass.getDeclaredMethod(getMethodName, new JavaClass[]{});
            }
            if(jMethod != null) {
                pType = jMethod.getReturnType();
                element = jMethod;
            } else {
                //look for a set method if type is set on javaAttribute
                for (Object next:jClass.getDeclaredMethods()) {
                    JavaMethod nextMethod = (JavaMethod)next;
                    if(nextMethod.getName().equals(setMethodName) && nextMethod.getParameterTypes().length == 1) {
                        pType = nextMethod.getParameterTypes()[0];
                        element = nextMethod;
                    }

                }
                if(element == null) {
                    return null;
                }
            }
        } else {
            JavaField jField = jClass.getDeclaredField(propName);
            if(jField == null) {
                return null;
            }
            pType = jField.getResolvedType();
            element = jField;
        }

        return this.aProcessor.buildNewProperty(info, jClass, element, propName, pType);
    }

    /**
     * Process a given JavaAtribute.
     *
     * @param javaAttribute
     * @param oldProperty
     * @param nsInfo
     * @return
     */
    private Property processJavaAttribute(TypeInfo typeInfo, JavaAttribute javaAttribute, Property oldProperty, NamespaceInfo nsInfo, JavaType javaType) {
         if (javaAttribute instanceof XmlVariableNode) {
             return processXmlVariableNodeAttribute((XmlVariableNode) javaAttribute, oldProperty, typeInfo, javaType);
         }
        if (javaAttribute instanceof XmlAnyAttribute) {
            return processXmlAnyAttribute((XmlAnyAttribute) javaAttribute, oldProperty, typeInfo, javaType);
        }
        if (javaAttribute instanceof XmlAnyElement) {
            return processXmlAnyElement((XmlAnyElement) javaAttribute, oldProperty, typeInfo, javaType);
        }
        if (javaAttribute instanceof XmlAttribute) {
            return processXmlAttribute((XmlAttribute) javaAttribute, oldProperty, typeInfo, nsInfo, javaType);
        }
        if (javaAttribute instanceof XmlElement) {
            return processXmlElement((XmlElement) javaAttribute, oldProperty, typeInfo, nsInfo, javaType);
        }
        if (javaAttribute instanceof XmlElements) {
            return processXmlElements((XmlElements) javaAttribute, oldProperty, typeInfo);
        }
        if (javaAttribute instanceof XmlElementRef) {
            return processXmlElementRef((XmlElementRef) javaAttribute, oldProperty, typeInfo);
        }
        if (javaAttribute instanceof XmlElementRefs) {
            return processXmlElementRefs((XmlElementRefs) javaAttribute, oldProperty, typeInfo);
        }
        if (javaAttribute instanceof XmlTransient) {
            return processXmlTransient((XmlTransient) javaAttribute, oldProperty);
        }
        if (javaAttribute instanceof XmlValue) {
            return processXmlValue((XmlValue) javaAttribute, oldProperty, typeInfo, javaType);
        }
        if (javaAttribute instanceof XmlJavaTypeAdapter) {
            return processXmlJavaTypeAdapter((XmlJavaTypeAdapter) javaAttribute, oldProperty);
        }
        if (javaAttribute instanceof XmlInverseReference) {
            return processXmlInverseReference((XmlInverseReference)javaAttribute, oldProperty, typeInfo);
        }
        if (javaAttribute instanceof XmlTransformation) {
            return processXmlTransformation((XmlTransformation)javaAttribute, oldProperty, typeInfo);
        }
        if (javaAttribute instanceof XmlJoinNodes) {
            return processXmlJoinNodes((XmlJoinNodes) javaAttribute, oldProperty, typeInfo);
        }
        getLogger().logWarning("jaxb_metadata_warning_invalid_java_attribute", new Object[] { javaAttribute.getClass() });
        return null;
    }

    /**
     * Handle property-level XmlJavaTypeAdapter
     *
     * @param xmlAdapter
     * @param oldProperty
     * @return
     */
    private Property processXmlJavaTypeAdapter(XmlJavaTypeAdapter xmlAdapter, Property oldProperty) {
        oldProperty.setXmlJavaTypeAdapter(xmlAdapter);
        return oldProperty;
    }

    /**
     * Handle xml-inverse-reference.
     *
     * @param xmlInverseReference
     * @param oldProperty
     * @return
     */
    private Property processXmlInverseReference(XmlInverseReference xmlInverseReference, Property oldProperty, TypeInfo info) {
        resetProperty(oldProperty, info);
        oldProperty.setInverseReference(true, false);
        oldProperty.setInverseReferencePropertyName(xmlInverseReference.getMappedBy());
        if (xmlInverseReference.getXmlAccessMethods() != null) {
            oldProperty.setInverseReferencePropertyGetMethodName(xmlInverseReference.getXmlAccessMethods().getGetMethod());
            oldProperty.setInverseReferencePropertySetMethodName(xmlInverseReference.getXmlAccessMethods().getSetMethod());
        }
        // set user-defined properties
        if (xmlInverseReference.getXmlProperties() != null  && xmlInverseReference.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlInverseReference.getXmlProperties().getXmlProperty()));
        }
        // check for container type
        if (!xmlInverseReference.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlInverseReference.getContainerType());
        }
        // set type
        if (!xmlInverseReference.getType().equals(DEFAULT)) {
            JavaClass pType = jModelInput.getJavaModel().getClass(xmlInverseReference.getType());
            if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) {
                oldProperty.setGenericType(pType);
            } else {
                oldProperty.setType(pType);
            }
            oldProperty.setHasXmlElementType(true);
            // may need to generate a type info for the type
            if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) {
                aProcessor.buildNewTypeInfo(new JavaClass[] { pType });
            }
        }
        return oldProperty;
    }

    /**
     * Handle xml-any-attribute.
     *
     * @param xmlAnyAttribute
     * @param oldProperty
     * @param tInfo
     * @param javaType
     * @return
     */
    private Property processXmlAnyAttribute(XmlAnyAttribute xmlAnyAttribute, Property oldProperty, TypeInfo tInfo, JavaType javaType) {
        // if oldProperty is already an Any (via @XmlAnyAttribute annotation)
        // there's nothing to do
        if (oldProperty.isAnyAttribute()) {
            return oldProperty;
        }

        // type has to be a java.util.Map
        if (!aProcessor.getHelper().isMapType(oldProperty.getType())) {
            if (oldProperty.getType().getClass().getName().contains("OXMJavaClassImpl")) {
                JavaClass pType = jModelInput.getJavaModel().getClass("java.util.Map");
                oldProperty.setType(pType);
            } else {
                throw org.eclipse.persistence.exceptions.JAXBException.anyAttributeOnNonMap(oldProperty.getPropertyName());
            }
        }

        // reset any existing values
        resetProperty(oldProperty, tInfo);

        oldProperty.setIsAnyAttribute(true);
        tInfo.setAnyAttributePropertyName(oldProperty.getPropertyName());

        // handle XmlPath
        if (xmlAnyAttribute.getXmlPath() != null) {
            oldProperty.setXmlPath(xmlAnyAttribute.getXmlPath());
        }
        // handle get/set methods
        if (xmlAnyAttribute.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlAnyAttribute.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlAnyAttribute.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlAnyAttribute.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlAnyAttribute.isReadOnly());
        }
        // handle write-only
        if (xmlAnyAttribute.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlAnyAttribute.isWriteOnly());
        }
        // set user-defined properties
        if (xmlAnyAttribute.getXmlProperties() != null  && xmlAnyAttribute.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlAnyAttribute.getXmlProperties().getXmlProperty()));
        }
        // check for container type
        if (!xmlAnyAttribute.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlAnyAttribute.getContainerType());
        }
        return oldProperty;
    }



    private Property processXmlVariableNodeAttribute(XmlVariableNode xmlVariableNode, Property oldProperty, TypeInfo tInfo, JavaType javaType) {
        processObjectFactory(tInfo);

        // reset any existing values
        resetProperty(oldProperty, tInfo);

        oldProperty.setVariableAttributeName(xmlVariableNode.getJavaVariableAttribute());
        String type = xmlVariableNode.getType();
        if(!type.equals(DEFAULT)){
            oldProperty.setVariableClassName(type);
        }

        if (xmlVariableNode.getXmlPath() != null) {
            oldProperty.setXmlPath(xmlVariableNode.getXmlPath());
        } else {
            // no xml-path, so use name/namespace from xml-element, and process wrapper
            XmlElementWrapper xmlElementWrapper = xmlVariableNode.getXmlElementWrapper();
            if (xmlElementWrapper != null) {
                if (DEFAULT.equals(xmlElementWrapper.getName())) {
                    xmlElementWrapper.setName(tInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName()));
                }
                oldProperty.setXmlElementWrapper(xmlVariableNode.getXmlElementWrapper());
            }
        }


        return oldProperty;
    }


    /**
     * Handle xml-any-element. If the property was annotated with @XmlAnyElement
     * in code all values will be overridden.
     *
     * @param xmlAnyElement
     * @param oldProperty
     * @param tInfo
     * @param javaType
     * @return
     */
    private Property processXmlAnyElement(XmlAnyElement xmlAnyElement, Property oldProperty, TypeInfo tInfo, JavaType javaType) {

        processObjectFactory(tInfo);

        // reset any existing values
        resetProperty(oldProperty, tInfo);

        // set xml-any-element specific properties
        oldProperty.setIsAny(true);
        oldProperty.setDomHandlerClassName(xmlAnyElement.getDomHandler());
        oldProperty.setLax(xmlAnyElement.isLax());
        oldProperty.setMixedContent(xmlAnyElement.isXmlMixed());
        oldProperty.setXmlJavaTypeAdapter(xmlAnyElement.getXmlJavaTypeAdapter());

        // update TypeInfo
        tInfo.setMixed(xmlAnyElement.isXmlMixed());
        tInfo.setAnyElementPropertyName(oldProperty.getPropertyName());

        // handle XmlPath
        if (xmlAnyElement.getXmlPath() != null) {
            oldProperty.setXmlPath(xmlAnyElement.getXmlPath());
        }
        // handle get/set methods
        if (xmlAnyElement.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlAnyElement.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlAnyElement.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlAnyElement.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlAnyElement.isReadOnly());
        }
        // handle write-only
        if (xmlAnyElement.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlAnyElement.isWriteOnly());
        }
        // set user-defined properties
        if (xmlAnyElement.getXmlProperties() != null  && xmlAnyElement.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlAnyElement.getXmlProperties().getXmlProperty()));
        }
        // check for container type
        if (!xmlAnyElement.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlAnyElement.getContainerType());
        }
        // check for xml-element-refs
        if (xmlAnyElement.getXmlElementRefs() != null) {
            oldProperty.setXmlElementRefs(xmlAnyElement.getXmlElementRefs().getXmlElementRef());
            oldProperty.setIsReference(true);

            boolean required = true;
            for (XmlElementRef eltRef : xmlAnyElement.getXmlElementRefs().getXmlElementRef()) {
                required = required && eltRef.isRequired();
            }
            oldProperty.setIsRequired(required);
            if (xmlAnyElement.getXmlElementRefs().isSetXmlMixed()) {
                oldProperty.setMixedContent(xmlAnyElement.getXmlElementRefs().isXmlMixed());
            }
        }

        return oldProperty;
    }

    /**
     * XmlAttribute override will completely replace the existing values.
     *
     * @param xmlAttribute
     * @param oldProperty
     * @param nsInfo
     * @return
     */
    private Property processXmlAttribute(XmlAttribute xmlAttribute, Property oldProperty, TypeInfo typeInfo, NamespaceInfo nsInfo, JavaType javaType) {
        // reset any existing values
        resetProperty(oldProperty, typeInfo);

        // handle xml-id
        if (xmlAttribute.isXmlId()) {
            oldProperty.setIsXmlId(true);
            oldProperty.setIsXmlIdExtension(true);
            typeInfo.setIDProperty(oldProperty);
        } else {
            // account for XmlID un-set via XML
            if (typeInfo.getIDProperty() != null && typeInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) {
                typeInfo.setIDProperty(null);
            }
        }

        // handle xml-idref
        oldProperty.setIsXmlIdRef(xmlAttribute.isXmlIdref());

        // handle xml-key
        if (xmlAttribute.isXmlKey()) {
            typeInfo.addXmlKeyProperty(oldProperty);
        }

        // set isAttribute
        oldProperty.setIsAttribute(true);

        // set xml-inline-binary-data
        oldProperty.setisInlineBinaryData(xmlAttribute.isXmlInlineBinaryData());

        String name;
        String namespace;

        // handle XmlPath
        // if xml-path is set, we ignore name/namespace
        if (xmlAttribute.getXmlPath() != null) {
            oldProperty.setXmlPath(xmlAttribute.getXmlPath());
            name = getNameFromXPath(xmlAttribute.getXmlPath(), oldProperty.getPropertyName(), true);
            namespace = DEFAULT;
        } else {
            // no xml-path, so use name/namespace from xml-attribute
            name = xmlAttribute.getName();
            namespace = xmlAttribute.getNamespace();
        }

        if (javaType.getXmlType() != null && javaType.getXmlType().getNamespace() != null  &&
                (xmlAttribute.getNamespace() != null && xmlAttribute.getNamespace().equals(DEFAULT))) {
            // Inherit type-level namespace if there is one
            namespace = javaType.getXmlType().getNamespace();
        }

        // set schema name
        QName qName;
        if (name.equals(DEFAULT)) {
            name = typeInfo.getXmlNameTransformer().transformAttributeName(oldProperty.getPropertyName());
        }
        if (namespace.equals(DEFAULT)) {
            if (nsInfo.isAttributeFormQualified()) {
                qName = new QName(nsInfo.getNamespace(), name);
            } else {
                qName = new QName(name);
            }
        } else {
            qName = new QName(namespace, name);
        }
        oldProperty.setSchemaName(qName);

        // check for container type
        if (!xmlAttribute.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlAttribute.getContainerType());
        }
        // set type
        if (!xmlAttribute.getType().equals(DEFAULT)) {
            JavaClass pType = jModelInput.getJavaModel().getClass(xmlAttribute.getType());
            if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) {
                oldProperty.setGenericType(pType);
            } else {
                oldProperty.setType(pType);
            }
            oldProperty.setHasXmlElementType(true);
            // may need to generate a type info for the type
            if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) {
                aProcessor.buildNewTypeInfo(new JavaClass[] { pType });
            }
        }

        reapplyPackageAndClassAdapters(oldProperty, typeInfo);
        // handle XmlJavaTypeAdapter
        if (xmlAttribute.getXmlJavaTypeAdapter() != null) {
            oldProperty.setXmlJavaTypeAdapter(xmlAttribute.getXmlJavaTypeAdapter());
        }

        // handle required - for required, if set by user than true/false;
        // if not set by user, true if property type == primitive
        if (xmlAttribute.isSetRequired()) {
            oldProperty.setIsRequired(xmlAttribute.isRequired());
        } else if (oldProperty.getActualType().isPrimitive()) {
            oldProperty.setIsRequired(true);
        }

        // handle xml-mime-type
        if (xmlAttribute.getXmlMimeType() != null) {
            oldProperty.setMimeType(xmlAttribute.getXmlMimeType());
        }

        // handle xml-attachment-ref
        if (xmlAttribute.isXmlAttachmentRef()) {
            oldProperty.setIsSwaAttachmentRef(true);
            oldProperty.setSchemaType(Constants.SWA_REF_QNAME);
        } else if (aProcessor.isMtomAttachment(oldProperty)) {
            oldProperty.setIsMtomAttachment(true);
            oldProperty.setSchemaType(Constants.BASE_64_BINARY_QNAME);
        }

        // handle xml-schema-type
        if (xmlAttribute.getXmlSchemaType() != null) {
            oldProperty.setSchemaType(new QName(xmlAttribute.getXmlSchemaType().getNamespace(), xmlAttribute.getXmlSchemaType().getName()));
        }
        // handle get/set methods
        if (xmlAttribute.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlAttribute.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlAttribute.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlAttribute.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlAttribute.isReadOnly());
        }
        // handle write-only
        if (xmlAttribute.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlAttribute.isWriteOnly());
        }
        // handle null policy
        if (xmlAttribute.getXmlAbstractNullPolicy() != null) {
            JAXBElement jaxbElt = xmlAttribute.getXmlAbstractNullPolicy();
            oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue());
        }
        // set user-defined properties
        if (xmlAttribute.getXmlProperties() != null  && xmlAttribute.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlAttribute.getXmlProperties().getXmlProperty()));
        }
        return oldProperty;
    }

    /**
     * XmlElement override will completely replace the existing values.
     *
     * @param xmlElement
     * @param oldProperty
     * @param typeInfo
     * @param nsInfo
     * @return
     */
    private Property processXmlElement(XmlElement xmlElement, Property oldProperty, TypeInfo typeInfo, NamespaceInfo nsInfo, JavaType javaType) {
        // reset any existing values
        resetProperty(oldProperty, typeInfo);

        if (xmlElement.getXmlMap() != null) {
            processXmlMap(xmlElement.getXmlMap(), oldProperty);
        }

        if (xmlElement.isXmlLocation()) {
            if (!aProcessor.getHelper().getJavaClass(Constants.LOCATOR_CLASS).isAssignableFrom(oldProperty.getType())) {
                throw JAXBException.invalidXmlLocation(oldProperty.getPropertyName(), oldProperty.getType().getName());
            }
            oldProperty.setXmlLocation(true);
        }

        // handle xml-id
        if (xmlElement.isXmlId()) {
            oldProperty.setIsXmlId(true);
            oldProperty.setIsXmlIdExtension(true);
            typeInfo.setIDProperty(oldProperty);
        } else {
            // account for XmlID un-set via XML
            if (typeInfo.getIDProperty() != null && typeInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) {
                typeInfo.setIDProperty(null);
            }
        }

        if(xmlElement.getXmlInverseReference() != null){
        String mappedBy = xmlElement.getXmlInverseReference().getMappedBy();
        oldProperty.setInverseReference(true, true);
            oldProperty.setInverseReferencePropertyName(mappedBy);
        }

        // handle xml-idref
        oldProperty.setIsXmlIdRef(xmlElement.isXmlIdref());

        // handle xml-key
        if (xmlElement.isXmlKey()) {
            typeInfo.addXmlKeyProperty(oldProperty);
        }

        // set required
        oldProperty.setIsRequired(xmlElement.isRequired());

        // set xml-inline-binary-data
        oldProperty.setisInlineBinaryData(xmlElement.isXmlInlineBinaryData());

        // set nillable
        oldProperty.setNillable(xmlElement.isNillable());

        // set defaultValue
        if (xmlElement.getDefaultValue().equals("\u0000")) {
            oldProperty.setDefaultValue(null);
        } else {
            oldProperty.setDefaultValue(xmlElement.getDefaultValue());
        }

        String name;
        String namespace;

        // handle XmlPath / XmlElementWrapper
        // if xml-path is set, we ignore xml-element-wrapper, as well as name/namespace on xml-element
        if (xmlElement.getXmlPath() != null) {
            oldProperty.setXmlPath(xmlElement.getXmlPath());
            name = getNameFromXPath(xmlElement.getXmlPath(), oldProperty.getPropertyName(), false);
            namespace = DEFAULT;
        } else {
            // no xml-path, so use name/namespace from xml-element, and process wrapper
            name = xmlElement.getName();
            namespace = xmlElement.getNamespace();
            XmlElementWrapper xmlElementWrapper = xmlElement.getXmlElementWrapper();
            if (xmlElementWrapper != null) {
                if (DEFAULT.equals(xmlElementWrapper.getName())) {
                    xmlElementWrapper.setName(typeInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName()));
                }
                oldProperty.setXmlElementWrapper(xmlElement.getXmlElementWrapper());
                if(oldProperty.isMap()){
                    name = xmlElement.getXmlElementWrapper().getName();
                    namespace = xmlElement.getXmlElementWrapper().getNamespace();
                }
            }
        }

        if (javaType.getXmlType() != null && javaType.getXmlType().getNamespace() != null  &&
                (xmlElement.getNamespace() != null && xmlElement.getNamespace().equals(DEFAULT))) {
            // Inherit type-level namespace if there is one
            namespace = javaType.getXmlType().getNamespace();
        }

        // set schema name
        QName qName;
        if (name.equals(DEFAULT)) {
            name = typeInfo.getXmlNameTransformer().transformElementName(oldProperty.getPropertyName());
        }
        if (namespace.equals(DEFAULT)) {
            if (nsInfo.isElementFormQualified()) {
                qName = new QName(nsInfo.getNamespace(), name);
            } else {
                qName = new QName(name);
            }
        } else {
            qName = new QName(namespace, name);
        }
        oldProperty.setSchemaName(qName);

        // check for container type
        if (!xmlElement.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlElement.getContainerType());
        }
        // set type
        if (xmlElement.getType().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT")) {
            // if xmlElement has no type, and the property type was set via
            // @XmlElement, reset it to the original value
            if (oldProperty.isXmlElementType()) {
                oldProperty.setType(oldProperty.getOriginalType());
            }
        } else if (xmlElement.getXmlMap() != null) {
            getLogger().logWarning(JAXBMetadataLogger.INVALID_TYPE_ON_MAP, new Object[] { xmlElement.getName() });
        } else {
            JavaClass pType = jModelInput.getJavaModel().getClass(xmlElement.getType());
            if(aProcessor.getHelper().isCollectionType(oldProperty.getType())) {
                oldProperty.setGenericType(pType);
            } else {
                oldProperty.setType(pType);
            }
            oldProperty.setHasXmlElementType(true);
            // may need to generate a type info for the type
            if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) {
                aProcessor.buildNewTypeInfo(new JavaClass[] { pType });
            }
        }

        reapplyPackageAndClassAdapters(oldProperty, typeInfo);
        // handle XmlJavaTypeAdapter
        if (xmlElement.getXmlJavaTypeAdapter() != null) {
            try {
                oldProperty.setXmlJavaTypeAdapter(xmlElement.getXmlJavaTypeAdapter());
            } catch(JAXBException e) {
                throw JAXBException.invalidPropertyAdapterClass(xmlElement.getXmlJavaTypeAdapter().getValue(), xmlElement.getJavaAttribute(), javaType.getName());
            }
        }

        // for primitives we always set required, a.k.a. minOccurs="1"
        if (!oldProperty.isRequired()) {
            JavaClass ptype = oldProperty.getActualType();
            oldProperty.setIsRequired(ptype.isPrimitive() || ptype.isArray() && ptype.getComponentType().isPrimitive());
        }

        // handle xml-list
        if (xmlElement.isSetXmlList()) {
            // Make sure XmlList annotation is on a collection or array
            if (!aProcessor.getHelper().isCollectionType(oldProperty.getType()) && !oldProperty.getType().isArray()) {
                throw JAXBException.invalidList(oldProperty.getPropertyName());
            }
            oldProperty.setIsXmlList(xmlElement.isXmlList());
        }

        // handle xml-mime-type
        if (xmlElement.getXmlMimeType() != null) {
            oldProperty.setMimeType(xmlElement.getXmlMimeType());
        }

        // handle xml-attachment-ref
        if (xmlElement.isXmlAttachmentRef()) {
            oldProperty.setIsSwaAttachmentRef(true);
            oldProperty.setSchemaType(Constants.SWA_REF_QNAME);
        } else if (aProcessor.isMtomAttachment(oldProperty)) {
            oldProperty.setIsMtomAttachment(true);
            oldProperty.setSchemaType(Constants.BASE_64_BINARY_QNAME);
        }

        // handle xml-schema-type
        if (xmlElement.getXmlSchemaType() != null) {
            oldProperty.setSchemaType(new QName(xmlElement.getXmlSchemaType().getNamespace(), xmlElement.getXmlSchemaType().getName()));
        }
        // handle get/set methods
        if (xmlElement.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlElement.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlElement.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlElement.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlElement.isReadOnly());
        }
        // handle write-only
        if (xmlElement.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlElement.isWriteOnly());
        }
        // handle cdata
        if (xmlElement.isSetCdata()) {
            oldProperty.setCdata(xmlElement.isCdata());
        }
        // handle null policy
        if (xmlElement.getXmlAbstractNullPolicy() != null) {
            JAXBElement jaxbElt = xmlElement.getXmlAbstractNullPolicy();
            oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue());
        }
        // set user-defined properties
        if (xmlElement.getXmlProperties() != null  && xmlElement.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlElement.getXmlProperties().getXmlProperty()));
        }
        return oldProperty;
    }

    private Property processXmlMap(XmlMap xmlMap, Property oldProperty) {
        XmlMap.Key mapKey = xmlMap.getKey();
        XmlMap.Value mapValue = xmlMap.getValue();

        if (mapKey != null && mapKey.getType() != null) {
            oldProperty.setKeyType(jModelInput.getJavaModel().getClass(mapKey.getType()));
        } else {
            oldProperty.setKeyType(jModelInput.getJavaModel().getClass(JAVA_LANG_OBJECT));
        }

        if (mapValue != null && mapValue.getType() != null) {
            oldProperty.setValueType(jModelInput.getJavaModel().getClass(mapValue.getType()));
        } else {
            oldProperty.setValueType(jModelInput.getJavaModel().getClass(JAVA_LANG_OBJECT));
        }

        return oldProperty;
    }

    /**
     * Process XmlElements.
     *
     * The XmlElements object will be set on the property, and it will be
     * flagged as a 'choice'.
     *
     * @param xmlElements
     * @param oldProperty
     * @param tInfo
     * @return
     */
    private Property processXmlElements(XmlElements xmlElements, Property oldProperty, TypeInfo tInfo) {
        resetProperty(oldProperty, tInfo);
        oldProperty.setChoice(true);
        oldProperty.setXmlElements(xmlElements);
        // handle idref
        oldProperty.setIsXmlIdRef(xmlElements.isXmlIdref());
        // handle XmlElementWrapper
        if (xmlElements.getXmlElementWrapper() != null) {
            oldProperty.setXmlElementWrapper(xmlElements.getXmlElementWrapper());
        }
        // handle get/set methods
        if (xmlElements.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlElements.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlElements.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlElements.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlElements.isReadOnly());
        }
        // handle write-only
        if (xmlElements.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlElements.isWriteOnly());
        }
        // set user-defined properties
        if (xmlElements.getXmlProperties() != null  && xmlElements.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlElements.getXmlProperties().getXmlProperty()));
        }
        // check for container type
        if (!xmlElements.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlElements.getContainerType());
        }
        // check for xml-join-nodes
        if (xmlElements.hasXmlJoinNodes()) {
            // store the List of XmlJoinNodes so we can access them when
            // we process the choice elements in AnnotationsProcessor
            oldProperty.setXmlJoinNodesList(xmlElements.getXmlJoinNodes());
        }
        // handle XmlJavaTypeAdapter
        if (xmlElements.getXmlJavaTypeAdapter() != null) {
            try {
                oldProperty.setXmlJavaTypeAdapter(xmlElements.getXmlJavaTypeAdapter());
            } catch(JAXBException e) {
                throw JAXBException.invalidPropertyAdapterClass(xmlElements.getXmlJavaTypeAdapter().getValue(), xmlElements.getJavaAttribute(), tInfo.getJavaClassName());
            }
        }
        return oldProperty;
    }

    /**
     * Process an xml-element-ref.
     *
     * @param xmlElementRef
     * @param oldProperty
     * @param info
     * @return
     */
    private Property processXmlElementRef(XmlElementRef xmlElementRef, Property oldProperty, TypeInfo info) {
        processObjectFactory(info);

        resetProperty(oldProperty, info);

        List<XmlElementRef> eltRefs = new ArrayList<XmlElementRef>();
        eltRefs.add(xmlElementRef);
        oldProperty.setXmlElementRefs(eltRefs);
        oldProperty.setIsReference(true);
        oldProperty.setIsRequired(xmlElementRef.isRequired());

        // handle XmlAdapter
        if (xmlElementRef.getXmlJavaTypeAdapter() != null) {
            oldProperty.setXmlJavaTypeAdapter(xmlElementRef.getXmlJavaTypeAdapter());
        }
        // check for container type
        if (!xmlElementRef.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlElementRef.getContainerType());
        }
        // handle XmlElementWrapper
        if (xmlElementRef.getXmlElementWrapper() != null) {
            oldProperty.setXmlElementWrapper(xmlElementRef.getXmlElementWrapper());
        }
        // set user-defined properties
        if (xmlElementRef.getXmlProperties() != null  && xmlElementRef.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlElementRef.getXmlProperties().getXmlProperty()));
        }
        if (xmlElementRef.isSetXmlMixed()) {
            oldProperty.setMixedContent(xmlElementRef.isXmlMixed());
        }
        // handle get/set methods
        if (xmlElementRef.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlElementRef.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlElementRef.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlElementRef.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlElementRef.isReadOnly());
        }
        // handle write-only
        if (xmlElementRef.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlElementRef.isWriteOnly());
        }
        return oldProperty;
    }

    /**
     * Process an xml-element-refs.
     *
     * @param xmlElementRefs
     * @param oldProperty
     * @param info
     * @return
     */
    private Property processXmlElementRefs(XmlElementRefs xmlElementRefs, Property oldProperty, TypeInfo info) {
        processObjectFactory(info);

        resetProperty(oldProperty, info);

        List<XmlElementRef> eltRefs = new ArrayList<XmlElementRef>();
        boolean required = true;
        for (XmlElementRef eltRef : xmlElementRefs.getXmlElementRef()) {
            eltRefs.add(eltRef);
            required = required && eltRef.isRequired();
        }

        oldProperty.setXmlElementRefs(eltRefs);
        oldProperty.setIsReference(true);
        oldProperty.setIsRequired(required);

        // handle XmlAdapter
        if (xmlElementRefs.getXmlJavaTypeAdapter() != null) {
            oldProperty.setXmlJavaTypeAdapter(xmlElementRefs.getXmlJavaTypeAdapter());
        }
        // handle XmlElementWrapper
        if (xmlElementRefs.getXmlElementWrapper() != null) {
            oldProperty.setXmlElementWrapper(xmlElementRefs.getXmlElementWrapper());
        }
        // set user-defined properties
        if (xmlElementRefs.getXmlProperties() != null  && xmlElementRefs.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlElementRefs.getXmlProperties().getXmlProperty()));
        }
        if (xmlElementRefs.isSetXmlMixed()) {
            oldProperty.setMixedContent(xmlElementRefs.isXmlMixed());
        }
        // handle get/set methods
        if (xmlElementRefs.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlElementRefs.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlElementRefs.getXmlAccessMethods().getSetMethod());
        }
        // handle read-only
        if (xmlElementRefs.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlElementRefs.isReadOnly());
        }
        // handle write-only
        if (xmlElementRefs.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlElementRefs.isWriteOnly());
        }
        return oldProperty;
    }

    private Property processXmlTransient(XmlTransient xmlTransient, Property oldProperty) {
        if (xmlTransient.isXmlLocation()) {
            if (!aProcessor.getHelper().getJavaClass(Constants.LOCATOR_CLASS).isAssignableFrom(oldProperty.getType())) {
                throw JAXBException.invalidXmlLocation(oldProperty.getPropertyName(), oldProperty.getType().getName());
            }
            oldProperty.setXmlLocation(true);
        }
        oldProperty.setTransient(true);
        return oldProperty;
    }

    private Property processXmlValue(XmlValue xmlValue, Property oldProperty, TypeInfo info, JavaType javaType) {
        // reset any existing values
        resetProperty(oldProperty, info);

        oldProperty.setIsXmlValue(true);
        oldProperty.setIsXmlValueExtension(true);
        info.setXmlValueProperty(oldProperty);

        // handle get/set methods
        if (xmlValue.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlValue.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlValue.getXmlAccessMethods().getSetMethod());
        }
        // check for container type
        if (!xmlValue.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlValue.getContainerType());
        }
        // set type
        if (!xmlValue.getType().equals(DEFAULT)) {
            JavaClass pType = jModelInput.getJavaModel().getClass(xmlValue.getType());
            if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) {
                oldProperty.setGenericType(pType);
            } else {
                oldProperty.setType(pType);
            }
            oldProperty.setHasXmlElementType(true);
            // may need to generate a type info for the type
            if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) {
                aProcessor.buildNewTypeInfo(new JavaClass[] { pType });
            }
        }

        reapplyPackageAndClassAdapters(oldProperty, info);
        // handle XmlJavaTypeAdapter
        if (xmlValue.getXmlJavaTypeAdapter() != null) {
            try {
                oldProperty.setXmlJavaTypeAdapter(xmlValue.getXmlJavaTypeAdapter());
            } catch(JAXBException e) {
                throw JAXBException.invalidPropertyAdapterClass(xmlValue.getXmlJavaTypeAdapter().getValue(), xmlValue.getJavaAttribute(), javaType.getName());
            }
        }
        // handle read-only
        if (xmlValue.isSetReadOnly()) {
            oldProperty.setReadOnly(xmlValue.isReadOnly());
        }
        // handle write-only
        if (xmlValue.isSetWriteOnly()) {
            oldProperty.setWriteOnly(xmlValue.isWriteOnly());
        }
        // handle cdata
        if (xmlValue.isSetCdata()) {
            oldProperty.setCdata(xmlValue.isCdata());
        }
        // handle null policy
        if (xmlValue.getXmlAbstractNullPolicy() != null) {
            JAXBElement jaxbElt = xmlValue.getXmlAbstractNullPolicy();
            oldProperty.setNullPolicy((XmlAbstractNullPolicy) jaxbElt.getValue());
        }
        // set user-defined properties
        if (xmlValue.getXmlProperties() != null  && xmlValue.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlValue.getXmlProperties().getXmlProperty()));
        }
        return oldProperty;
    }

    /**
     * Process an XmlSchema. This involves creating a NamespaceInfo instance and
     * populating it based on the given XmlSchema.
     *
     * @param xmlBindings
     * @param packageName
     * @see NamespaceInfo
     * @see AnnotationsProcessor
     * @return newly created namespace info, or null if schema is null
     */
    private NamespaceInfo processXmlSchema(XmlBindings xmlBindings, String packageName) {
        XmlSchema schema = xmlBindings.getXmlSchema();
        if (schema == null) {
            return null;
        }
        // create NamespaceInfo
        NamespaceInfo nsInfo = this.aProcessor.findInfoForNamespace(schema.getNamespace());
        if(nsInfo == null) {
            nsInfo = new NamespaceInfo();
        }
        // process XmlSchema
        XmlNsForm form = schema.getAttributeFormDefault();
        nsInfo.setAttributeFormQualified(form.equals(XmlNsForm.QUALIFIED));
        form = schema.getElementFormDefault();
        nsInfo.setElementFormQualified(form.equals(XmlNsForm.QUALIFIED));


        if (!nsInfo.isElementFormQualified() || nsInfo.isAttributeFormQualified()) {
            aProcessor.setDefaultNamespaceAllowed(false);
        }

        // make sure defaults are set, not null
        nsInfo.setLocation(schema.getLocation() == null ? GENERATE : schema.getLocation());
        String namespace = schema.getNamespace();
        if(namespace == null) {
            namespace = this.aProcessor.getDefaultTargetNamespace();
        }
        nsInfo.setNamespace(namespace == null ? "" : schema.getNamespace());
        NamespaceResolver nsr = new NamespaceResolver();
        // process XmlNs
        for (XmlNs xmlns : schema.getXmlNs()) {
            nsr.put(xmlns.getPrefix(), xmlns.getNamespaceUri());
        }
        nsInfo.setNamespaceResolver(nsr);
        return nsInfo;
    }

    /**
     * Process an XmlTransformation. The info in the XmlTransformation will be
     * used to generate an XmlTransformationMapping in MappingsGenerator.
     *
     * @param xmlTransformation
     * @param oldProperty
     * @param tInfo
     */
    private Property processXmlTransformation(XmlTransformation xmlTransformation, Property oldProperty, TypeInfo tInfo) {
        // reset any existing values
        resetProperty(oldProperty, tInfo);

        oldProperty.setIsXmlTransformation(true);
        oldProperty.setXmlTransformation(xmlTransformation);

        // handle get/set methods
        if (xmlTransformation.getXmlAccessMethods() != null) {
            oldProperty.setMethodProperty(true);
            oldProperty.setGetMethodName(xmlTransformation.getXmlAccessMethods().getGetMethod());
            oldProperty.setSetMethodName(xmlTransformation.getXmlAccessMethods().getSetMethod());
        }
        // set user-defined properties
        if (xmlTransformation.getXmlProperties() != null  && xmlTransformation.getXmlProperties().getXmlProperty().size() > 0) {
            oldProperty.setUserProperties(createUserPropertyMap(xmlTransformation.getXmlProperties().getXmlProperty()));
        }
        aProcessor.getReferencedByTransformer().add(oldProperty.getType().getName());
        return oldProperty;
    }

    /**
     * Process XmlJoinNodes.  This method sets the XmlJoinNodes instance on the Property
     * for use in MappingsGen and SchemaGen.
     *
     * @param xmlJoinNodes
     * @param oldProperty
     * @return
     */
    private Property processXmlJoinNodes(XmlJoinNodes xmlJoinNodes, Property oldProperty, TypeInfo typeInfo) {
        // reset any existing values
        resetProperty(oldProperty, typeInfo);

        oldProperty.setXmlJoinNodes(xmlJoinNodes);

        // check for container type
        if (!xmlJoinNodes.getContainerType().equals(DEFAULT)) {
            setContainerType(oldProperty, xmlJoinNodes.getContainerType());
        }
        // set type
        if (!xmlJoinNodes.getType().equals(DEFAULT)) {
            JavaClass pType = jModelInput.getJavaModel().getClass(xmlJoinNodes.getType());
            if (aProcessor.getHelper().isCollectionType(oldProperty.getType())) {
                oldProperty.setGenericType(pType);
            } else {
                oldProperty.setType(pType);
            }
            oldProperty.setHasXmlElementType(true);
            // may need to generate a type info for the type
            if (aProcessor.shouldGenerateTypeInfo(pType) && aProcessor.getTypeInfos().get(pType.getQualifiedName()) == null) {
                aProcessor.buildNewTypeInfo(new JavaClass[] { pType });
            }
        }
        return oldProperty;
    }

    /**
     * Convenience method for building a Map of package to classes.
     *
     * @return
     */
    private Map<String, ArrayList<JavaClass>> buildPackageToJavaClassMap() {
        Map<String, ArrayList<JavaClass>> theMap = new HashMap<String, ArrayList<JavaClass>>();
        Map<String, ArrayList<JavaClass>> xmlBindingsMap = new HashMap<String, ArrayList<JavaClass>>();

        XmlBindings xmlBindings;
        for (String packageName : xmlBindingMap.keySet()) {
            xmlBindings = xmlBindingMap.get(packageName);
            ArrayList classes = new ArrayList<JavaClass>();
            // add binding classes - the Java Model will be used to get a
            // JavaClass via class name
            JavaTypes jTypes = xmlBindings.getJavaTypes();
            if (jTypes != null) {
                for (JavaType javaType : jTypes.getJavaType()) {
                    addClassToList(classes, javaType.getName(), packageName);
                }
            }

            // add any enum types to the class list
            XmlEnums xmlEnums = xmlBindings.getXmlEnums();
            if (xmlEnums != null) {
                for (XmlEnum xmlEnum : xmlEnums.getXmlEnum()) {
                    addClassToList(classes, xmlEnum.getJavaEnum(), packageName);
                }
            }

            theMap.put(packageName, classes);
            xmlBindingsMap.put(packageName, new ArrayList(classes));
        }

        // add any other classes that aren't declared via external metadata
        for (JavaClass jClass : jModelInput.getJavaClasses()) {
            // need to verify that the class isn't already in the bindings file
            // list
            String pkg = jClass.getPackageName();
            ArrayList<JavaClass> existingXmlBindingsClasses = xmlBindingsMap.get(pkg);
            ArrayList<JavaClass> allExistingClasses = theMap.get(pkg);
            if (existingXmlBindingsClasses != null) {
                if (!classExistsInArray(jClass, existingXmlBindingsClasses)) {
                    allExistingClasses.add(jClass);
                }
            } else {
                if (allExistingClasses != null) {
                    allExistingClasses.add(jClass);
                } else {
                    ArrayList classes = new ArrayList<JavaClass>();
                    classes.add(jClass);
                    theMap.put(pkg, classes);
                }
            }
        }

        return theMap;
    }


    private void addClassToList(List classes, String name, String packageName){
        JavaClass nextClass = jModelInput.getJavaModel().getClass(getQualifiedJavaTypeName(name, packageName));
        String nextPackageName = nextClass.getPackageName();
        if(nextPackageName == null || !nextPackageName.equals(packageName)){
            throw JAXBException.javaTypeNotAllowedInBindingsFile(nextPackageName, packageName);
        }
        classes.add(nextClass);
    }
    /**
     * Lazy load the metadata logger.
     *
     * @return
     */
    private JAXBMetadataLogger getLogger() {
        if (logger == null) {
            logger = new JAXBMetadataLogger();
        }
        return logger;
    }

    /**
     * Convenience method to determine if a class exists in a given ArrayList.
     * The classes are compared via equals() method.
     */
    public boolean classExistsInArray(JavaClass theClass, ArrayList<JavaClass> existingClasses) {
        return aProcessor.getHelper().classExistsInArray(theClass, existingClasses);
    }

    /**
     * Convenience method for resetting a number of properties on a given
     * property.
     *
     * @param oldProperty
     * @return
     */
    private Property resetProperty(Property oldProperty, TypeInfo tInfo) {
        oldProperty.setIsAttribute(false);
        oldProperty.setHasXmlElementType(false);
        oldProperty.setIsRequired(false);
        oldProperty.setIsXmlList(false);
        oldProperty.setXmlJavaTypeAdapter(null);
        oldProperty.setInverseReferencePropertyName(null);
        oldProperty.setDefaultValue(null);
        oldProperty.setDomHandlerClassName(null);
        oldProperty.setIsSwaAttachmentRef(false);
        oldProperty.setIsXmlIdRef(false);
        oldProperty.setIsXmlTransformation(false);
        oldProperty.setXmlElementWrapper(null);
        oldProperty.setLax(false);
        oldProperty.setNillable(false);
        oldProperty.setMixedContent(false);
        oldProperty.setMimeType(null);
        oldProperty.setTransient(false);
        oldProperty.setChoice(false);
        oldProperty.setIsReference(false);
        oldProperty.setXmlPath(null);
        oldProperty.setReadOnly(false);
        oldProperty.setWriteOnly(false);
        oldProperty.setCdata(false);
        oldProperty.setNullPolicy(null);
        oldProperty.setUserProperties(null);
        oldProperty.setGetMethodName(oldProperty.getOriginalGetMethodName());
        oldProperty.setSetMethodName(oldProperty.getOriginalSetMethodName());
        oldProperty.setXmlTransformation(null);
        oldProperty.setXmlJoinNodes(null);
        if (oldProperty.getGetMethodName() == null && oldProperty.getSetMethodName() == null) {
            oldProperty.setMethodProperty(false);
        }

        oldProperty.setIsSwaAttachmentRef(false);
        oldProperty.setIsMtomAttachment(false);
        oldProperty.setSchemaType(null);

        unsetXmlElementRefs(oldProperty, tInfo);
        unsetXmlElements(oldProperty);
        unsetXmlAnyAttribute(oldProperty, tInfo);
        unsetXmlAnyElement(oldProperty, tInfo);
        unsetXmlValue(oldProperty, tInfo);
        unsetXmlID(oldProperty, tInfo);
        unsetXmlKey(oldProperty, tInfo);
        return oldProperty;
    }

    /**
     * Ensure that a given property is not set as an xml-id.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlID(Property oldProperty, TypeInfo tInfo) {
        oldProperty.setIsXmlId(false);
        oldProperty.setIsXmlIdExtension(false);
        if (tInfo.isIDSet() && tInfo.getIDProperty().getPropertyName().equals(oldProperty.getPropertyName())) {
            tInfo.setIDProperty(null);
        }
    }

    /**
     * Ensure that a given property is not set as an xml-key.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlKey(Property oldProperty, TypeInfo tInfo) {
        if (tInfo.hasXmlKeyProperties()) {
            Property propToRemove = null;
            for (Property prop : tInfo.getXmlKeyProperties()) {
                if (prop.getPropertyName().equals(oldProperty.getPropertyName())) {
                    propToRemove = prop;
                }
            }
            if (propToRemove != null) {
                tInfo.getXmlKeyProperties().remove(propToRemove);
            }
        }
    }

    /**
     * Ensure that a given property is not set as an xml-element-refs.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlElementRefs(Property oldProperty, TypeInfo tInfo) {
        if (tInfo.hasElementRefs() && tInfo.getElementRefsPropName().equals(oldProperty.getPropertyName())) {
            tInfo.setElementRefsPropertyName(null);
        }
    }

    /**
     * Ensure that a given property is not set as an xml-elements.
     *
     * @param oldProperty
     */
    private void unsetXmlElements(Property oldProperty) {
        oldProperty.setXmlElements(null);
        oldProperty.setChoiceProperties(null);
    }

    /**
     * Ensure that a given property is not set as an xml-any-attribute.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlAnyAttribute(Property oldProperty, TypeInfo tInfo) {
        oldProperty.setIsAnyAttribute(false);
        if (tInfo.isSetAnyAttributePropertyName() && tInfo.getAnyAttributePropertyName().equals(oldProperty.getPropertyName())) {
            tInfo.setAnyAttributePropertyName(null);
        }
    }

    /**
     * Ensure that a given property is not set as an xml-any-element.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlAnyElement(Property oldProperty, TypeInfo tInfo) {
        oldProperty.setIsAny(false);
        if (tInfo.isSetAnyElementPropertyName() && tInfo.getAnyElementPropertyName().equals(oldProperty.getPropertyName())) {
            tInfo.setAnyElementPropertyName(null);
        }
    }

    /**
     * Ensure that a given property is not set as an xml-value.
     *
     * @param oldProperty
     * @param tInfo
     */
    private void unsetXmlValue(Property oldProperty, TypeInfo tInfo) {
        oldProperty.setIsXmlValue(false);
        oldProperty.setIsXmlValueExtension(false);
        if (tInfo.isSetXmlValueProperty() && tInfo.getXmlValueProperty().getPropertyName().equals(oldProperty.getPropertyName())) {
            tInfo.setXmlValueProperty(null);
        }
    }

    /**
     * Convenience method that returns the field name for a given xml-path.  This method
     * would typically be called when building a QName to set as the 'SchemaName' on
     * a Property.
     *
     * Examples:
     * - returns 'id' for xml-path '@id'
     * - returns 'managerId' for xml-path 'projects/prj:project/@prj:managerId'
     * - returns 'first-name' for xml-path 'info/personal-info/first-name/text()'
     * - returns 'project' for xml-path 'projects/prj:project/text()'
     * - returns 'data' for xml-path 'pieces-of-data/data[1]/text()'
     *
     * @param xpath
     * @param propertyName
     * @param isAttribute
     * @return
     */
    public static String getNameFromXPath(String xpath, String propertyName, boolean isAttribute) {
        // handle self mapping
        if (xpath.equals(SELF)) {
            return propertyName;
        }

        String name;
        String path;

        // may need to strip off '/text()'
        int idx = xpath.indexOf(SLASH + Constants.TEXT);
        if (idx >= 0) {
            path = xpath.substring(0, idx);
        } else {
            path = xpath;
        }

        idx = path.lastIndexOf(SLASH);
        if (idx >= 0 && path.length() > 1) {
            name = path.substring(idx+1);
            // may have a prefix
            StringTokenizer stok = new StringTokenizer(name, Character.toString(COLON));
            if (stok.countTokens() == 2) {
                // first token is prefix
                stok.nextToken();
                // second token is the field name
                name = stok.nextToken();
            }
        } else {
            name = path;
        }
        // may need to strip off '@'
        if (isAttribute) {
            idx = name.indexOf(Constants.ATTRIBUTE);
            if (idx >= 0 && name.length() > 1) {
                name = name.substring(idx+1);
            }
        } else {
            // may need to strip of positional info
            idx = name.indexOf(OPEN_BRACKET);
            if (idx != -1) {
                name = name.substring(0, idx);
            }
        }
        return name;
    }

    private void processObjectFactory(TypeInfo tInfo){
          int index = tInfo.getJavaClassName().lastIndexOf('.');
          if(index > -1){
            String objectFactoryClassName = tInfo.getJavaClassName().substring(0, index) + ".ObjectFactory";
            aProcessor.findAndProcessObjectFactory(objectFactoryClassName);
          }else{
            aProcessor.findAndProcessObjectFactory("ObjectFactory");
          }
    }


    /**
     * Return a Map of user-defined properties.  Typically the key will
     * be a String (property name) and the value a String or some
     * other simple type that was converted by ConversionManager,
     * i.e. numerical, boolean, temporal.
     *
     * @param propList
     * @return
     */
    private Map createUserPropertyMap(List<XmlProperty> propList) {
        return mergeUserPropertyMap(propList, new HashMap());
    }

    /**
     * Return a Map of user-defined properties. The List of properties (from
     * xml) will be merged with the given Map (from annotations).  In the
     * case of a conflict, xml will win.
     *
     * Note that this intended to be used when processing type-level user
     * properties, as at the property-level, xml completely replaces any
     * properties set via annotation.
     *
     * Typically the key will be a String (property name) and the value a
     * String or some other simple type that was converted by
     * ConversionManager, i.e. numerical, boolean, temporal.
     *
     * @param propList
     * @return
     */
    private Map mergeUserPropertyMap(List<XmlProperty> propList, Map existingMap) {
        Map propMap = existingMap;
        for (XmlProperty prop : propList) {
            Object pvalue = prop.getValue();
            if (prop.isSetValueType()) {
                pvalue = XMLConversionManager.getDefaultXMLManager().convertObject(
                        prop.getValue(), XMLConversionManager.getDefaultXMLManager().convertClassNameToClass(prop.getValueType()));
            }
            propMap.put(prop.getName(), pvalue);
        }
        return propMap;
    }

    /**
     * Convenience method for setting the container class on a given property.
     * The generic type will be overwritten, and could be incorrect after
     * doing so, so the original generic type will be retrieved and set after
     * the call to set the container type.
     *
     * @param property
     * @param containerClassName
     */
    private void setContainerType(Property property, String containerClassName) {
        // store the original generic type as the call to setType will overwrite it
        JavaClass genericType = property.getGenericType();
        // set the type to the container-type value
        property.setType(jModelInput.getJavaModel().getClass(containerClassName));
        // set the original generic type
        property.setGenericType(genericType);
    }

    /**
     * This method checks for class and package level adapters after the type of a property has been set.
     * @param prop the property that needs to be updated
     * @param owningInfo the typeInfo that represents the owner of this property.
     */
    public void reapplyPackageAndClassAdapters(Property prop, TypeInfo owningInfo) {
        if(prop.getXmlJavaTypeAdapter() != null) {
            //if there's already a property level adapter, don't apply package/class level
            return;
        }
        JavaClass type = prop.getActualType();
        //if a class level adapter is present on the target class, set it
        TypeInfo targetInfo = aProcessor.getTypeInfos().get(type.getQualifiedName());
        if(targetInfo != null) {
            if(targetInfo.getXmlJavaTypeAdapter() != null) {
                prop.setXmlJavaTypeAdapter(targetInfo.getXmlJavaTypeAdapter());
            }
        }

        //check for package level adapter. Don't overwrite class level
        if(owningInfo.hasPackageLevelAdaptersByClass()) {
            JavaClass packageLevelAdapter = owningInfo.getPackageLevelAdaptersByClass().get(type.getQualifiedName());
            if(packageLevelAdapter != null && prop.getXmlJavaTypeAdapter() == null) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
                xja.setValue(packageLevelAdapter.getQualifiedName());
                xja.setType(type.getQualifiedName());
               prop.setXmlJavaTypeAdapter(xja);
            }
        }
    }

    /**
     * This method is used to merge several bindings files into one XMLBindings object.
     * @param bindings the list of XmlBindings objects to merge.
     * @return XmlBindings object representing the merged files.
     */
    public static XmlBindings mergeXmlBindings(List<XmlBindings> bindings) {
        if(bindings.size() == 0) {
            return null;
        }
        XmlBindings rootBindings = bindings.get(0);
        for(int i = 1; i < bindings.size(); i++) {
            XmlBindings nextBindings = bindings.get(i);
            if(nextBindings.isSetXmlAccessorOrder()) {
                rootBindings.setXmlAccessorOrder(nextBindings.getXmlAccessorOrder());
            }
            if(nextBindings.isSetXmlAccessorType()) {
                rootBindings.setXmlAccessorType(nextBindings.getXmlAccessorType());
            }
            if(nextBindings.isSetXmlMappingMetadataComplete()) {
                rootBindings.setXmlMappingMetadataComplete(nextBindings.isXmlMappingMetadataComplete());
            }
            mergeJavaTypes(rootBindings.getJavaTypes(), nextBindings.getJavaTypes());

            if(rootBindings.getXmlEnums() == null) {
                rootBindings.setXmlEnums(nextBindings.getXmlEnums());
            } else {
                mergeXmlEnums(rootBindings.getXmlEnums(), nextBindings.getXmlEnums());
            }

            if(rootBindings.getXmlSchema() == null) {
                rootBindings.setXmlSchema(nextBindings.getXmlSchema());
            } else if(nextBindings.getXmlSchema() != null){
                mergeXmlSchema(rootBindings.getXmlSchema(), nextBindings.getXmlSchema());
            }

            if(rootBindings.getXmlSchemaType() == null) {
                rootBindings.setXmlSchemaTypes(nextBindings.getXmlSchemaTypes());
            } else if(nextBindings.getXmlSchemaTypes() != null){
                mergeXmlSchemaTypes(rootBindings.getXmlSchemaTypes(), nextBindings.getXmlSchemaTypes());
            }

            if(rootBindings.getXmlJavaTypeAdapters() == null) {
                rootBindings.setXmlJavaTypeAdapters(nextBindings.getXmlJavaTypeAdapters());
            } else if(nextBindings.getXmlJavaTypeAdapters() != null){
                mergeXmlJavaTypeAdapters(rootBindings.getXmlJavaTypeAdapters(), nextBindings.getXmlJavaTypeAdapters());
            }

            if (rootBindings.getXmlNullPolicy() == null) {
                rootBindings.setXmlNullPolicy(nextBindings.getXmlNullPolicy());
            } else if (nextBindings.getXmlNullPolicy() != null) {
                mergeXmlNullPolicy(rootBindings.getXmlNullPolicy(), nextBindings.getXmlNullPolicy());
            }

            if (rootBindings.getXmlElementNillable() == null) {
                rootBindings.setXmlElementNillable(nextBindings.getXmlElementNillable());
            } else if (nextBindings.getXmlElementNillable() != null) {
                mergeXmlElementNillable(rootBindings.getXmlElementNillable(), nextBindings.getXmlElementNillable());
            }
        }
        return rootBindings;
    }

    private static void mergeXmlElementNillable(XmlElementNillable xmlElementNillable, XmlElementNillable overrideXmlElementNillable) {
        xmlElementNillable.setNillable(overrideXmlElementNillable.isNillable());
    }

    private static void mergeXmlNullPolicy(XmlNullPolicy xmlNullPolicy, XmlNullPolicy overrideXmlNullPolicy) {
        xmlNullPolicy.setEmptyNodeRepresentsNull(overrideXmlNullPolicy.isEmptyNodeRepresentsNull());
        xmlNullPolicy.setIsSetPerformedForAbsentNode(overrideXmlNullPolicy.isIsSetPerformedForAbsentNode());
        xmlNullPolicy.setNullRepresentationForXml(overrideXmlNullPolicy.getNullRepresentationForXml());
        xmlNullPolicy.setXsiNilRepresentsNull(overrideXmlNullPolicy.isXsiNilRepresentsNull());
    }

    private static void mergeXmlJavaTypeAdapters(XmlJavaTypeAdapters xmlJavaTypeAdapters, XmlJavaTypeAdapters overrideAdapters) {
        List<XmlJavaTypeAdapter> adapterList = xmlJavaTypeAdapters.getXmlJavaTypeAdapter();
        HashMap<String, XmlJavaTypeAdapter> adapterMap = new HashMap<String, XmlJavaTypeAdapter>(adapterList.size());
        for(XmlJavaTypeAdapter next:adapterList) {
            adapterMap.put(next.getType(), next);
        }

        for(XmlJavaTypeAdapter next:overrideAdapters.getXmlJavaTypeAdapter()) {
            //If there's already an adapter for this type, replace it's value
            XmlJavaTypeAdapter existingAdapter = adapterMap.get(next.getType());
            if(existingAdapter != null) {
                existingAdapter.setValue(next.getValue());
            } else {
                xmlJavaTypeAdapters.getXmlJavaTypeAdapter().add(next);
            }
        }
    }

    private static void mergeXmlSchemaTypes(XmlSchemaTypes xmlSchemaTypes, XmlSchemaTypes overrideSchemaTypes) {
        List<XmlSchemaType> schemaTypeList = xmlSchemaTypes.getXmlSchemaType();
        HashMap<String, XmlSchemaType> schemaTypeMap = new HashMap<String, XmlSchemaType>(schemaTypeList.size());
        for(XmlSchemaType next:schemaTypeList) {
            schemaTypeMap.put(next.getType(), next);
        }

        for(XmlSchemaType next:overrideSchemaTypes.getXmlSchemaType()) {
            //if there's already a schemaType for this type, override it's value
            XmlSchemaType existingType = schemaTypeMap.get(next.getType());
            if(existingType != null) {
                existingType.setName(next.getName());
                existingType.setNamespace(next.getNamespace());
            } else {
                xmlSchemaTypes.getXmlSchemaType().add(next);
            }
        }
    }

    private static void mergeXmlSchema(XmlSchema xmlSchema, XmlSchema overrideSchema) {

        xmlSchema.setAttributeFormDefault(overrideSchema.getAttributeFormDefault());
        xmlSchema.setElementFormDefault(overrideSchema.getElementFormDefault());
        xmlSchema.setLocation(overrideSchema.getLocation());
        xmlSchema.setNamespace(overrideSchema.getNamespace());
        List<XmlNs> xmlNsList = xmlSchema.getXmlNs();
        xmlNsList.addAll(overrideSchema.getXmlNs());
    }

    private static void mergeXmlEnums(XmlEnums xmlEnums, XmlEnums overrideEnum) {
        if(overrideEnum == null) {
            return;
        }
        List<XmlEnum> enumList = xmlEnums.getXmlEnum();
        Map<String, XmlEnum> enumMap = new HashMap<String, XmlEnum>(enumList.size());
        for(XmlEnum next:enumList) {
            enumMap.put(next.getJavaEnum(), next);
        }
        for(XmlEnum next:overrideEnum.getXmlEnum()) {
            XmlEnum existingEnum = enumMap.get(next.getJavaEnum());
            if(existingEnum != null) {
                mergeXmlEnumValues(existingEnum.getXmlEnumValue(), next.getXmlEnumValue());
            } else {
                xmlEnums.getXmlEnum().add(next);
            }
        }
    }

    private static void mergeXmlEnumValues(List<XmlEnumValue> xmlEnumValue, List<XmlEnumValue> overrideXmlEnumValue) {

        Map<String, XmlEnumValue> values = new HashMap<String, XmlEnumValue>();
        List<XmlEnumValue> extraValues = new ArrayList<XmlEnumValue>();
        for(XmlEnumValue next:xmlEnumValue){
            values.put(next.getJavaEnumValue(), next);
        }

        for(XmlEnumValue next:overrideXmlEnumValue) {
            XmlEnumValue existingValue = values.get(next.getJavaEnumValue());
            if(existingValue == null) {
                extraValues.add(next);
            } else {
                existingValue.setValue(next.getValue());
            }
        }
        xmlEnumValue.addAll(extraValues);
    }

    private static void mergeJavaTypes(JavaTypes javaTypes, JavaTypes overrideJavaTypes) {
        List<JavaType> javaTypeList = javaTypes.getJavaType();
        Map<String, JavaType> javaTypeMap = new HashMap<String, JavaType>(javaTypeList.size());
        for(JavaType next:javaTypeList) {
            javaTypeMap.put(next.getName(), next);
        }
        for(JavaType next:overrideJavaTypes.getJavaType()) {
            JavaType existingType = javaTypeMap.get(next.getName());
            if(existingType == null) {
                javaTypes.getJavaType().add(next);
            } else {
                mergeJavaType(existingType, next);
            }
        }
    }

    private static void mergeJavaType(JavaType existingType, JavaType next) {
        if(next.isSetXmlAccessorOrder()) {
            existingType.setXmlAccessorOrder(next.getXmlAccessorOrder());
        }

        if(next.isSetXmlAccessorType()) {
            existingType.setXmlAccessorType(next.getXmlAccessorType());
        }

        if(next.isSetXmlInlineBinaryData()) {
            existingType.setXmlInlineBinaryData(next.isXmlInlineBinaryData());
        }

        if(next.isSetXmlTransient()) {
            existingType.setXmlTransient(next.isXmlInlineBinaryData());
        }

        if(next.getXmlRootElement() != null) {
            existingType.setXmlRootElement(next.getXmlRootElement());
        }

        if(existingType.getXmlProperties() == null) {
            existingType.setXmlProperties(next.getXmlProperties());
        } else if(next.getXmlProperties() != null) {
            existingType.getXmlProperties().getXmlProperty().addAll(next.getXmlProperties().getXmlProperty());
        }

        if(next.getXmlType() != null) {
            existingType.setXmlType(next.getXmlType());
        }

        existingType.getXmlSeeAlso().addAll(next.getXmlSeeAlso());


        JavaAttributes attributes = existingType.getJavaAttributes();
        JavaAttributes overrideAttributes = next.getJavaAttributes();
        if(attributes == null) {
            existingType.setJavaAttributes(overrideAttributes);
        } else if(overrideAttributes != null) {
            mergeJavaAttributes(attributes, overrideAttributes, existingType);
        }

    }

    private static void mergeJavaAttributes(JavaAttributes attributes, JavaAttributes overrideAttributes, JavaType javaType) {
        List<JAXBElement<? extends JavaAttribute>> attributeList = attributes.getJavaAttribute();
        Map<String, JAXBElement> attributeMap = new HashMap<String, JAXBElement>(attributeList.size());

        for(JAXBElement next:attributeList) {
            attributeMap.put(((JavaAttribute)next.getValue()).getJavaAttribute(), next);
        }
        for(JAXBElement next:overrideAttributes.getJavaAttribute()) {
            JAXBElement existingAttribute = attributeMap.get(((JavaAttribute)next.getValue()).getJavaAttribute());
            if(existingAttribute != null) {
                attributes.getJavaAttribute().remove(existingAttribute);
            }
            attributes.getJavaAttribute().add(next);
        }
    }
}
