/*
 * 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:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.jaxb.compiler;

import java.awt.Image;
import java.beans.Introspector;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import jakarta.validation.constraints.Size;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.annotation.XmlAccessorOrder;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAnyAttribute;
import jakarta.xml.bind.annotation.XmlAnyElement;
import jakarta.xml.bind.annotation.XmlAttachmentRef;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlElementDecl;
import jakarta.xml.bind.annotation.XmlElementRef;
import jakarta.xml.bind.annotation.XmlElementRefs;
import jakarta.xml.bind.annotation.XmlElementWrapper;
import jakarta.xml.bind.annotation.XmlElements;
import jakarta.xml.bind.annotation.XmlEnum;
import jakarta.xml.bind.annotation.XmlEnumValue;
import jakarta.xml.bind.annotation.XmlID;
import jakarta.xml.bind.annotation.XmlIDREF;
import jakarta.xml.bind.annotation.XmlInlineBinaryData;
import jakarta.xml.bind.annotation.XmlList;
import jakarta.xml.bind.annotation.XmlMimeType;
import jakarta.xml.bind.annotation.XmlMixed;
import jakarta.xml.bind.annotation.XmlNs;
import jakarta.xml.bind.annotation.XmlNsForm;
import jakarta.xml.bind.annotation.XmlRegistry;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlSchema;
import jakarta.xml.bind.annotation.XmlSchemaType;
import jakarta.xml.bind.annotation.XmlSchemaTypes;
import jakarta.xml.bind.annotation.XmlTransient;
import jakarta.xml.bind.annotation.XmlType;
import jakarta.xml.bind.annotation.XmlType.DEFAULT;
import jakarta.xml.bind.annotation.XmlValue;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapters;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;

import org.eclipse.persistence.exceptions.ConversionException;
import org.eclipse.persistence.exceptions.JAXBException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.jaxb.AccessorFactoryWrapper;
import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.internal.jaxb.many.ArrayValue;
import org.eclipse.persistence.internal.jaxb.many.CollectionValue;
import org.eclipse.persistence.internal.jaxb.many.ManyValue;
import org.eclipse.persistence.internal.jaxb.many.MultiDimensionalArrayValue;
import org.eclipse.persistence.internal.jaxb.many.MultiDimensionalCollectionValue;
import org.eclipse.persistence.internal.libraries.asm.AnnotationVisitor;
import org.eclipse.persistence.internal.libraries.asm.ClassWriter;
import org.eclipse.persistence.internal.libraries.asm.EclipseLinkASMClassWriter;
import org.eclipse.persistence.internal.libraries.asm.FieldVisitor;
import org.eclipse.persistence.internal.libraries.asm.Label;
import org.eclipse.persistence.internal.libraries.asm.MethodVisitor;
import org.eclipse.persistence.internal.libraries.asm.Opcodes;
import org.eclipse.persistence.internal.libraries.asm.Type;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.Namespace;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.jaxb.MOXySystemProperties;
import org.eclipse.persistence.jaxb.TypeMappingInfo;
import org.eclipse.persistence.jaxb.compiler.facets.DecimalMaxFacet;
import org.eclipse.persistence.jaxb.compiler.facets.DecimalMinFacet;
import org.eclipse.persistence.jaxb.compiler.facets.DigitsFacet;
import org.eclipse.persistence.jaxb.compiler.facets.MaxFacet;
import org.eclipse.persistence.jaxb.compiler.facets.MinFacet;
import org.eclipse.persistence.jaxb.compiler.facets.PatternFacet;
import org.eclipse.persistence.jaxb.compiler.facets.PatternListFacet;
import org.eclipse.persistence.jaxb.compiler.facets.SizeFacet;
import org.eclipse.persistence.jaxb.javamodel.AnnotationProxy;
import org.eclipse.persistence.jaxb.javamodel.Helper;
import org.eclipse.persistence.jaxb.javamodel.JavaAnnotation;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.JavaConstructor;
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.JavaPackage;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaFieldImpl;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAccessOrder;
import org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlReadTransformer;
import org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlWriteTransformer;
import org.eclipse.persistence.mappings.transformers.AttributeTransformer;
import org.eclipse.persistence.mappings.transformers.FieldTransformer;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLNameTransformer;
import org.eclipse.persistence.oxm.annotations.XmlAccessMethods;
import org.eclipse.persistence.oxm.annotations.XmlCDATA;
import org.eclipse.persistence.oxm.annotations.XmlClassExtractor;
import org.eclipse.persistence.oxm.annotations.XmlCustomizer;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorNode;
import org.eclipse.persistence.oxm.annotations.XmlDiscriminatorValue;
import org.eclipse.persistence.oxm.annotations.XmlElementNillable;
import org.eclipse.persistence.oxm.annotations.XmlElementsJoinNodes;
import org.eclipse.persistence.oxm.annotations.XmlIDExtension;
import org.eclipse.persistence.oxm.annotations.XmlInverseReference;
import org.eclipse.persistence.oxm.annotations.XmlIsSetNullPolicy;
import org.eclipse.persistence.oxm.annotations.XmlJoinNode;
import org.eclipse.persistence.oxm.annotations.XmlJoinNodes;
import org.eclipse.persistence.oxm.annotations.XmlKey;
import org.eclipse.persistence.oxm.annotations.XmlLocation;
import org.eclipse.persistence.oxm.annotations.XmlNameTransformer;
import org.eclipse.persistence.oxm.annotations.XmlNamedAttributeNode;
import org.eclipse.persistence.oxm.annotations.XmlNamedObjectGraph;
import org.eclipse.persistence.oxm.annotations.XmlNamedObjectGraphs;
import org.eclipse.persistence.oxm.annotations.XmlNamedSubgraph;
import org.eclipse.persistence.oxm.annotations.XmlNullPolicy;
import org.eclipse.persistence.oxm.annotations.XmlParameter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
import org.eclipse.persistence.oxm.annotations.XmlPaths;
import org.eclipse.persistence.oxm.annotations.XmlProperties;
import org.eclipse.persistence.oxm.annotations.XmlProperty;
import org.eclipse.persistence.oxm.annotations.XmlReadOnly;
import org.eclipse.persistence.oxm.annotations.XmlValueExtension;
import org.eclipse.persistence.oxm.annotations.XmlVariableNode;
import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;
import org.eclipse.persistence.oxm.annotations.XmlWriteOnly;
import org.eclipse.persistence.oxm.annotations.XmlWriteTransformers;

/**
 * INTERNAL:
 * <p>
 * <b>Purpose:</b>To perform some initial processing of Java classes and JAXB
 * 2.0 Annotations and generate meta data that can be used by the Mappings
 * Generator and Schema Generator
 * <p>
 * <b>Responsibilities:</b>
 * <ul>
 * <li>Generate a map of TypeInfo objects, keyed on class name</li>
 * <li>Generate a map of user defined schema types</li>
 * <li>Identify any class-based JAXB 2.0 callback methods, and create
 * MarshalCallback and UnmarshalCallback objects to wrap them.</li>
 * <li>Centralize processing which is common to both Schema Generation and
 * Mapping Generation tasks</li>
 * </ul>
 * <p>
 * This class does the initial processing of the JAXB 2.0 Generation. It
 * generates meta data that can be used by the later Schema Generation and
 * Mapping Generation steps.
 *
 * @see org.eclipse.persistence.jaxb.compiler.Generator
 * @author mmacivor
 * @since Oracle TopLink 11.1.1.0.0
 */
public final class AnnotationsProcessor {

    static final String ARRAY_PACKAGE_NAME = "jaxb.dev.java.net.array";
    static final String JAVAX_ACTIVATION_DATAHANDLER = "jakarta.activation.DataHandler";
    static final String JAVAX_MAIL_INTERNET_MIMEMULTIPART = "jakarta.mail.internet.MimeMultipart";
    private static final String JAVAX_XML_BIND_JAXBELEMENT = "jakarta.xml.bind.JAXBElement";
    private static final String JAVAX_XML_BIND_ANNOTATION = "jakarta.xml.bind.annotation";
    private static final String OXM_ANNOTATIONS = "org.eclipse.persistence.oxm.annotations";
    private static final String TYPE_METHOD_NAME = "type";
    private static final String VALUE_METHOD_NAME = "value";
    private static final String ARRAY_NAMESPACE = "http://jaxb.dev.java.net/array";
    private static final String ARRAY_CLASS_NAME_SUFFIX = "Array";
    private static final String JAXB_DEV = "jaxb.dev.java.net";
    private static final String ORG_W3C_DOM = "org.w3c.dom";
    private static final String CREATE = "create";
    private static final String ELEMENT_DECL_GLOBAL = "jakarta.xml.bind.annotation.XmlElementDecl.GLOBAL";
    private static final String ELEMENT_DECL_DEFAULT = "\u0000";
    private static final String EMPTY_STRING = "";
    private static final String JAVA_UTIL_LIST = "java.util.List";
    private static final String JAVA_LANG_OBJECT = "java.lang.Object";
    private static final String SLASH = "/";
    private static final String SEMI_COLON = ";";
    private static final String L = "L";
    private static final String ITEM = "item";
    private static final String IS_STR = "is";
    private static final String GET_STR = "get";
    private static final String SET_STR = "set";
    private static final Character DOT_CHR = '.';
    private static final Character DOLLAR_SIGN_CHR = '$';
    private static final Character SLASH_CHR = '/';

    private List<JavaClass> typeInfoClasses;
    private Map<String, PackageInfo> packageToPackageInfoMappings;
    private HashMap<String, XmlNillableInfo> packageToXmlNillableInfoMappings;
    private Map<String, MarshalCallback> marshalCallbacks;
    private Map<String, QName> userDefinedSchemaTypes;
    private Map<String, TypeInfo> typeInfos;
    private List<QName> typeQNames;
    private Map<String, UnmarshalCallback> unmarshalCallbacks;
    private Map<String, Map<QName, ElementDeclaration>> elementDeclarations;
    private Map<String, ElementDeclaration> xmlRootElements;
    private List<ElementDeclaration> localElements;
    private Map<String, JavaMethod> factoryMethods;
    private Map<String, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry> xmlRegistries;
    private List<String> objectFactoryClassNames;
    private List<JavaClass> classesToProcessPropertyTypes;

    private Map<String, Class> arrayClassesToGeneratedClasses;
    private Map<Class, JavaClass> generatedClassesToArrayClasses;
    private Map<java.lang.reflect.Type, Class> collectionClassesToGeneratedClasses;
    private Map<Class, java.lang.reflect.Type> generatedClassesToCollectionClasses;
    private Map<JavaClass, List<TypeMappingInfo>> javaClassToTypeMappingInfos;
    private Map<TypeMappingInfo, Class> typeMappingInfosToGeneratedClasses;
    private Map<TypeMappingInfo, Class> typeMappingInfoToAdapterClasses;
    private Map<TypeMappingInfo, QName> typeMappingInfosToSchemaTypes;

    private Helper helper;
    private String defaultTargetNamespace;

    private JAXBMetadataLogger logger;

    private boolean isDefaultNamespaceAllowed;
    private boolean xmlAccessorFactorySupport;

    private boolean hasSwaRef;

    private List<String> referencedByTransformer;
    private boolean hasXmlBindings = false;
    private boolean facets;

    public AnnotationsProcessor(Helper helper) {
        this.helper = helper;
        this.facets = helper.isFacets();
        isDefaultNamespaceAllowed = true;
        hasSwaRef = false;
    }

    /**
     * This event is called when annotation processing is completed,
     * and provides a chance to deference anything that is no longer
     * needed (to reduce the memory footprint of this object).
     */
    void postInitialize() {
        typeInfoClasses = null;
        packageToPackageInfoMappings = null;
        typeInfos = null;
        typeQNames = null;
        elementDeclarations = null;
        xmlRootElements = null;
        localElements = null;
        factoryMethods = null;
        xmlRegistries = null;
        objectFactoryClassNames = null;
        classesToProcessPropertyTypes = null;
        javaClassToTypeMappingInfos = null;
        typeMappingInfosToGeneratedClasses = null;
        typeMappingInfoToAdapterClasses = null;
        helper = null;
        logger = null;
        referencedByTransformer = null;
    }

    /**
     * Generate TypeInfo instances for a given array of JavaClasses.
     *
     */
    void processClassesAndProperties(JavaClass[] classes, TypeMappingInfo[] typeMappingInfos) {
        init(classes, typeMappingInfos);
        preBuildTypeInfo(classes);
        postBuildTypeInfo(classes);
        processPropertyTypes(this.typeInfoClasses.toArray(new JavaClass[this.typeInfoClasses.size()]));
        finalizeProperties();
        createElementsForTypeMappingInfo();
        checkForCallbackMethods();
    }

    public void createElementsForTypeMappingInfo() {
        if (javaClassToTypeMappingInfos != null && !javaClassToTypeMappingInfos.isEmpty()) {
            Set<JavaClass> classes = this.javaClassToTypeMappingInfos.keySet();
            for (JavaClass nextClass : classes) {
                List<TypeMappingInfo> nextInfos = this.javaClassToTypeMappingInfos.get(nextClass);
                for(TypeMappingInfo nextInfo:nextInfos) {
                    if (nextInfo != null) {
                        boolean xmlAttachmentRef = false;
                        String xmlMimeType = null;
                        java.lang.annotation.Annotation[] annotations = getAnnotations(nextInfo);
                        Class adapterClass = typeMappingInfoToAdapterClasses.get(nextInfo);
                        Class declJavaType = null;
                        if (adapterClass != null) {
                            declJavaType = CompilerHelper.getTypeFromAdapterClass(adapterClass);
                        }
                        if (annotations != null) {
                            for (Annotation nextAnnotation : annotations) {
                                if (nextAnnotation != null) {
                                    if (nextAnnotation instanceof XmlMimeType) {
                                        XmlMimeType javaAnnotation = (XmlMimeType) nextAnnotation;
                                        xmlMimeType = javaAnnotation.value();
                                    } else if (nextAnnotation instanceof XmlAttachmentRef) {
                                        xmlAttachmentRef = true;
                                        if (!this.hasSwaRef) {
                                            this.hasSwaRef = true;
                                        }
                                    }
                                }
                            }
                        }

                        QName qname;

                        String nextClassName = nextClass.getQualifiedName();

                        if (declJavaType != null) {
                            nextClassName = declJavaType.getCanonicalName();
                        }

                        if (typeMappingInfosToGeneratedClasses != null) {
                            Class generatedClass = typeMappingInfosToGeneratedClasses.get(nextInfo);
                            if (generatedClass != null) {
                                nextClassName = generatedClass.getCanonicalName();
                            }
                        }

                        TypeInfo nextTypeInfo = typeInfos.get(nextClassName);
                        if (nextTypeInfo != null) {
                            qname = new QName(nextTypeInfo.getClassNamespace(), nextTypeInfo.getSchemaTypeName());
                        } else {
                            qname = getUserDefinedSchemaTypes().get(nextClassName);
                            if (qname == null) {
                                if (nextClassName.equals(ClassConstants.APBYTE.getName()) || nextClassName.equals(Image.class.getName()) || nextClassName.equals(Source.class.getName()) || nextClassName.equals("jakarta.activation.DataHandler")) {
                                    if (xmlAttachmentRef) {
                                        qname = Constants.SWA_REF_QNAME;
                                    } else {
                                        qname = Constants.BASE_64_BINARY_QNAME;
                                    }
                                } else if (nextClassName.equals(ClassConstants.OBJECT.getName())) {
                                    qname = Constants.ANY_TYPE_QNAME;
                                } else if (nextClassName.equals(ClassConstants.XML_GREGORIAN_CALENDAR.getName())) {
                                    qname = Constants.ANY_SIMPLE_TYPE_QNAME;
                                } else {
                                    Class theClass = helper.getClassForJavaClass(nextClass);
                                    qname = XMLConversionManager.getDefaultJavaTypes().get(theClass);
                                }
                            }
                        }

                        if (qname != null) {
                            typeMappingInfosToSchemaTypes.put(nextInfo, qname);
                        }

                        if (nextInfo.getXmlTagName() != null) {
                            ElementDeclaration element = new ElementDeclaration(nextInfo.getXmlTagName(), nextClass, nextClass.getQualifiedName(), false);
                            element.setTypeMappingInfo(nextInfo);
                            element.setXmlMimeType(xmlMimeType);
                            element.setXmlAttachmentRef(xmlAttachmentRef);
                            element.setNillable(nextInfo.isNillable());

                            if (declJavaType != null) {
                                element.setJavaType(helper.getJavaClass(declJavaType));
                            }
                            Class generatedClass = typeMappingInfosToGeneratedClasses.get(nextInfo);
                            if (generatedClass != null) {
                                element.setJavaType(helper.getJavaClass(generatedClass));
                            }
                            if (nextInfo.getElementScope() == TypeMappingInfo.ElementScope.Global) {
                                ElementDeclaration currentElement = this.getGlobalElements().get(element.getElementName());
                                if (currentElement == null) {
                                    addGlobalElement(element.getElementName(), element);
                                } else {
                                    //  if(currentElement.getTypeMappingInfo() == null) {
                                    //  the global element that exists came from an annotation

                                    //} else {
                                    this.localElements.add(element);
                                    //}
                                }
                            } else {
                                this.localElements.add(element);
                            }
                            String rootNamespace = element.getElementName().getNamespaceURI();
                            if (rootNamespace == null) {
                                rootNamespace = Constants.EMPTY_STRING;
                            }
                            if (rootNamespace.equals(Constants.EMPTY_STRING)) {
                                isDefaultNamespaceAllowed = false;
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * Returns an array of Annotations for a given TypeMappingInfo. This array
     * will either be populated from the TypeMappingInfo's array of annotations,
     * or based on an xml-element if present. The xml-element will take
     * precedence over the annotation array; if there is an xml-element the
     * Array of Annotations will be ignored.
     *
     */
    private java.lang.annotation.Annotation[] getAnnotations(TypeMappingInfo tmInfo) {
        if (tmInfo.getXmlElement() != null) {
            ClassLoader loader = helper.getClassLoader();
            // create a single ConversionManager for that will be shared by the
            // proxy objects
            ConversionManager cMgr = new ConversionManager();
            cMgr.setLoader(loader);

            // unmarshal the node into an XmlElement
            org.eclipse.persistence.jaxb.xmlmodel.XmlElement xElt = CompilerHelper.getXmlElement(tmInfo.getXmlElement(), loader);
            List annotations = new ArrayList();
            // where applicable, a given dynamic proxy will contain a Map of
            // method name/return value entries
            Map<String, Object> components = null;
            // handle @XmlElement: set 'type' method
            if (!(xElt.getType().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT"))) {
                components = new HashMap<String, Object>();
                components.put(TYPE_METHOD_NAME, xElt.getType());
                annotations.add(AnnotationProxy.getProxy(components, XmlElement.class, loader, cMgr));
            }
            // handle @XmlList
            if (xElt.isXmlList()) {
                annotations.add(AnnotationProxy.getProxy(components, XmlList.class, loader, cMgr));
            }
            // handle @XmlAttachmentRef
            if (xElt.isXmlAttachmentRef()) {
                annotations.add(AnnotationProxy.getProxy(components, XmlAttachmentRef.class, loader, cMgr));
            }
            // handle @XmlMimeType: set 'value' method
            if (xElt.getXmlMimeType() != null) {
                components = new HashMap<String, Object>();
                components.put(VALUE_METHOD_NAME, xElt.getXmlMimeType());
                annotations.add(AnnotationProxy.getProxy(components, XmlMimeType.class, loader, cMgr));
            }
            // handle @XmlJavaTypeAdapter: set 'type' and 'value' methods
            if (xElt.getXmlJavaTypeAdapter() != null) {
                components = new HashMap<String, Object>();
                components.put(TYPE_METHOD_NAME, xElt.getXmlJavaTypeAdapter().getType());
                components.put(VALUE_METHOD_NAME, xElt.getXmlJavaTypeAdapter().getValue());
                annotations.add(AnnotationProxy.getProxy(components, XmlJavaTypeAdapter.class, loader, cMgr));
            }
            // return the newly created array of dynamic proxy objects
            return (java.lang.annotation.Annotation[]) annotations.toArray(new java.lang.annotation.Annotation[annotations.size()]);
        }
        // no xml-element set on the info, (i.e. no xml overrides) so return the
        // array of Annotation objects
        return tmInfo.getAnnotations();
    }

    /**
     * Initialize maps, lists, etc. Typically called prior to processing a set
     * of classes via preBuildTypeInfo, postBuildTypeInfo, processJavaClasses.
     */
    void init(JavaClass[] classes, TypeMappingInfo[] typeMappingInfos) {
        typeInfoClasses = new ArrayList<JavaClass>();
        referencedByTransformer = new ArrayList<String>();
        typeInfos = new HashMap<String, TypeInfo>();
        typeQNames = new ArrayList<QName>();
        classesToProcessPropertyTypes = new ArrayList<JavaClass>();
        objectFactoryClassNames = new ArrayList<String>();
        userDefinedSchemaTypes = new HashMap<String, QName>();
        if (packageToPackageInfoMappings == null) {
            packageToPackageInfoMappings = new HashMap<String, PackageInfo>();
        }
        this.factoryMethods = new HashMap<String, JavaMethod>();
        this.xmlRegistries = new HashMap<String, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry>();
        this.xmlRootElements = new HashMap<String, ElementDeclaration>();

        arrayClassesToGeneratedClasses = new HashMap<String, Class>();
        collectionClassesToGeneratedClasses = new HashMap<java.lang.reflect.Type, Class>();
        generatedClassesToArrayClasses = new HashMap<Class, JavaClass>();
        generatedClassesToCollectionClasses = new HashMap<Class, java.lang.reflect.Type>();
        typeMappingInfosToGeneratedClasses = new HashMap<TypeMappingInfo, Class>();
        typeMappingInfosToSchemaTypes = new HashMap<TypeMappingInfo, QName>();
        elementDeclarations = new HashMap<String, Map<QName, ElementDeclaration>>();
        Map globalElements = new HashMap<QName, ElementDeclaration>();
        elementDeclarations.put(XmlElementDecl.GLOBAL.class.getName(), globalElements);
        localElements = new ArrayList<ElementDeclaration>();

        javaClassToTypeMappingInfos = new HashMap<JavaClass, List<TypeMappingInfo>>();
        typeMappingInfoToAdapterClasses = new HashMap<TypeMappingInfo, Class>();
        if (typeMappingInfos != null) {
            for (int i = 0; i < typeMappingInfos.length; i++) {
                List<TypeMappingInfo> infos = javaClassToTypeMappingInfos.get(classes[i]);
                if(infos == null) {
                    infos = new ArrayList<TypeMappingInfo>();
                    javaClassToTypeMappingInfos.put(classes[i], infos);
                }
                infos.add(typeMappingInfos[i]);

                java.lang.annotation.Annotation[] annotations = getAnnotations(typeMappingInfos[i]);
                if (annotations != null) {
                    for (java.lang.annotation.Annotation nextAnnotation : annotations) {
                        if (nextAnnotation instanceof XmlJavaTypeAdapter) {
                            typeMappingInfoToAdapterClasses.put(typeMappingInfos[i], ((XmlJavaTypeAdapter) nextAnnotation).value());
                        }
                    }
                }
            }
        }
    }

    /**
     * Process class level annotations only. It is assumed that a call to init()
     * has been made prior to calling this method. After the types created via
     * this method have been modified (if necessary) postBuildTypeInfo and
     * processJavaClasses should be called to finish processing.
     *
     */
    public Map<String, TypeInfo> preBuildTypeInfo(JavaClass[] javaClasses) {
        for (JavaClass javaClass : javaClasses) {
            String qualifiedName = javaClass.getQualifiedName();
            TypeInfo info = typeInfos.get(qualifiedName);
            if (javaClass == null || javaClass.isArray()|| (info!=null && info.isPreBuilt()) || !shouldGenerateTypeInfo(javaClass) || isXmlRegistry(javaClass) ) {
                continue;
            }


            if (javaClass.isEnum()) {
                info = new EnumTypeInfo(helper, javaClass);
            } else {
                info = new TypeInfo(helper, javaClass);
            }
            info.setJavaClassName(qualifiedName);
            info.setPreBuilt(true);

            // handle @XmlTransient
            if (helper.isAnnotationPresent(javaClass, XmlTransient.class)) {
                info.setXmlTransient(true);
            }

            // handle @XmlElementNillable
            processXmlElementNillable(javaClass, info);

            // handle @XmlExtensible
            processXmlExtensible(javaClass, info);

            // handle @XmlInlineBinaryData
            if (helper.isAnnotationPresent(javaClass, XmlInlineBinaryData.class)) {
                info.setInlineBinaryData(true);
            }

            // handle @NamedObjectGraph
            processNamedObjectGraphs(javaClass, info);

            // handle @XmlRootElement
            processXmlRootElement(javaClass, info);

            // handle @XmlSeeAlso
            processXmlSeeAlso(javaClass, info);

            PackageInfo packageInfo = getPackageInfoForPackage(javaClass);
            if(packageInfo != null && packageInfo.getPackageLevelAdaptersByClass().size() > 0){
                for(String adapterClass :packageInfo.getPackageLevelAdaptersByClass().keySet()){
                    JavaClass boundType = packageInfo.getPackageLevelAdaptersByClass().get(adapterClass);
                    info.getPackageLevelAdaptersByClass().put(adapterClass, boundType);
                }
            }
            NamespaceInfo namespaceInfo = packageInfo.getNamespaceInfo();
            // handle @XmlType
            preProcessXmlType(javaClass, info, namespaceInfo);

            // handle @XmlAccessorType
            preProcessXmlAccessorType(javaClass, info, namespaceInfo);

            // handle @XmlAccessorOrder
            preProcessXmlAccessorOrder(javaClass, info, namespaceInfo);

            // handle package level @XmlJavaTypeAdapters
            processPackageLevelAdapters(javaClass, info);

            // handle Accessor Factory
            processAccessorFactory(javaClass, info);

            // handle class level @XmlJavaTypeAdapters
            processClassLevelAdapters(javaClass, info);

            // handle descriptor customizer
            preProcessCustomizer(javaClass, info);

            // handle package level @XmlSchemaType(s)
            processSchemaTypes(javaClass, info);

            // handle class extractor
            if (helper.isAnnotationPresent(javaClass, XmlClassExtractor.class)) {
                XmlClassExtractor classExtractor = (XmlClassExtractor) helper.getAnnotation(javaClass, XmlClassExtractor.class);
                info.setClassExtractorName(classExtractor.value().getName());
            }

            // handle user properties
            if (helper.isAnnotationPresent(javaClass, XmlProperties.class)) {
                XmlProperties xmlProperties = (XmlProperties) helper.getAnnotation(javaClass, XmlProperties.class);
                Map<Object, Object> propertiesMap = createUserPropertiesMap(xmlProperties.value());
                info.setUserProperties(propertiesMap);
            } else if (helper.isAnnotationPresent(javaClass, XmlProperty.class)) {
                XmlProperty xmlProperty = (XmlProperty) helper.getAnnotation(javaClass, XmlProperty.class);
                Map<Object, Object> propertiesMap = createUserPropertiesMap(new XmlProperty[] { xmlProperty });
                info.setUserProperties(propertiesMap);
            }

            // handle class indicator field name
            if (helper.isAnnotationPresent(javaClass, XmlDiscriminatorNode.class)) {
                XmlDiscriminatorNode xmlDiscriminatorNode = (XmlDiscriminatorNode) helper.getAnnotation(javaClass, XmlDiscriminatorNode.class);
                info.setXmlDiscriminatorNode(xmlDiscriminatorNode.value());
            }
            // handle class indicator
            if (helper.isAnnotationPresent(javaClass, XmlDiscriminatorValue.class)) {
                XmlDiscriminatorValue xmlDiscriminatorValue = (XmlDiscriminatorValue) helper.getAnnotation(javaClass, XmlDiscriminatorValue.class);
                info.setXmlDiscriminatorValue(xmlDiscriminatorValue.value());
            }

            typeInfoClasses.add(javaClass);
            typeInfos.put(info.getJavaClassName(), info);
        }
        return typeInfos;
    }

    private void processXmlElementNillable(JavaClass javaClass, TypeInfo info) {
        if (helper.isAnnotationPresent(javaClass, XmlElementNillable.class)) {
            XmlElementNillable xmlElementNillable = (XmlElementNillable) helper.getAnnotation(javaClass, XmlElementNillable.class);
            info.setXmlElementNillable(xmlElementNillable.nillable());
        } else if (hasExternalPackageMapping(javaClass)) {
            info.setXmlElementNillable(packageToXmlNillableInfoMappings.get(javaClass.getPackageName()).getXmlElementNillable().isNillable());
        } else if (helper.isAnnotationPresent(javaClass.getPackage(), XmlElementNillable.class)) {
            XmlElementNillable xmlElementNillable = (XmlElementNillable) helper.getAnnotation(javaClass.getPackage(), XmlElementNillable.class);
            info.setXmlElementNillable(xmlElementNillable.nillable());
        }
    }

    private boolean hasExternalPackageMapping(JavaClass javaClass) {

        if (null == packageToXmlNillableInfoMappings || !packageToXmlNillableInfoMappings.containsKey(javaClass.getPackageName())) {
            return false;
        }

        return null != packageToXmlNillableInfoMappings.get(javaClass.getPackageName()).getXmlElementNillable();
    }

    private void processNamedObjectGraphs(JavaClass javaClass, TypeInfo info) {
        List<XmlNamedObjectGraph> objectGraphs = new ArrayList<XmlNamedObjectGraph>();
        if(helper.isAnnotationPresent(javaClass, XmlNamedObjectGraphs.class)) {
            XmlNamedObjectGraphs graphs = (XmlNamedObjectGraphs)helper.getAnnotation(javaClass, XmlNamedObjectGraphs.class);
            Collections.addAll(objectGraphs, graphs.value());
        }
        if(helper.isAnnotationPresent(javaClass, XmlNamedObjectGraph.class)) {
            objectGraphs.add((XmlNamedObjectGraph)helper.getAnnotation(javaClass, XmlNamedObjectGraph.class));
        }

        for(XmlNamedObjectGraph next:objectGraphs) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlNamedObjectGraph namedGraph = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedObjectGraph();
            namedGraph.setName(next.name());

            for(XmlNamedAttributeNode nextNode:next.attributeNodes()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode namedNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode();
                namedNode.setName(nextNode.value());
                namedNode.setSubgraph(nextNode.subgraph());
                namedGraph.getXmlNamedAttributeNode().add(namedNode);
            }
            for(XmlNamedSubgraph nextSubgraph:next.subgraphs()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlNamedSubgraph namedSubGraph = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedSubgraph();
                namedSubGraph.setName(nextSubgraph.name());
                namedSubGraph.setType(nextSubgraph.type().getName());
                for(XmlNamedAttributeNode nextNode:nextSubgraph.attributeNodes()) {
                    org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode namedNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode();
                    namedNode.setName(nextNode.value());
                    namedNode.setSubgraph(nextNode.subgraph());
                    namedSubGraph.getXmlNamedAttributeNode().add(namedNode);
                }
                namedGraph.getXmlNamedSubgraph().add(namedSubGraph);
            }
            for(XmlNamedSubgraph nextSubgraph:next.subclassSubgraphs()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlNamedSubgraph namedSubGraph = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedSubgraph();
                namedSubGraph.setName(nextSubgraph.name());
                namedSubGraph.setType(nextSubgraph.type().getName());
                for(XmlNamedAttributeNode nextNode:nextSubgraph.attributeNodes()) {
                    org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode namedNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlNamedAttributeNode();
                    namedNode.setName(nextNode.value());
                    namedNode.setSubgraph(nextNode.subgraph());
                    namedSubGraph.getXmlNamedAttributeNode().add(namedNode);
                }
                namedGraph.getXmlNamedSubclassGraph().add(namedSubGraph);
            }
            info.getObjectGraphs().add(namedGraph);
        }
    }

    private void processAccessorFactory(JavaClass javaClass, TypeInfo info) {
        if (!xmlAccessorFactorySupport) {
            return;
        }

        Annotation xmlAccessorFactory = helper.getAnnotation(javaClass, CompilerHelper.ACCESSOR_FACTORY_ANNOTATION_CLASS);
        Method valueMethod = null;
        if(xmlAccessorFactory != null) {
            valueMethod = CompilerHelper.ACCESSOR_FACTORY_VALUE_METHOD;
        } else {
            //try for internal annotation
            xmlAccessorFactory = helper.getAnnotation(javaClass, CompilerHelper.INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS);
            if(xmlAccessorFactory != null) {
                valueMethod = CompilerHelper.INTERNAL_ACCESSOR_FACTORY_VALUE_METHOD;
            }
        }
        if(xmlAccessorFactory != null) {
            Class xmlAccessorFactoryClass = null;
            try {
                xmlAccessorFactoryClass = PrivilegedAccessHelper.invokeMethod(valueMethod, xmlAccessorFactory, new Object[]{});
                info.setXmlAccessorFactory(new AccessorFactoryWrapper(PrivilegedAccessHelper.newInstanceFromClass(xmlAccessorFactoryClass)));
            } catch (Exception ex) {
                throw JAXBException.errorInstantiatingAccessorFactory(xmlAccessorFactoryClass, ex);
            }
        }
        PackageInfo pInfo = getPackageInfoForPackage(javaClass);
        if(pInfo != null) {
            info.setPackageLevelXmlAccessorFactory(pInfo.getAccessorFactory());
        }
    }

    /**
     * Process any additional classes (i.e. inner classes, @XmlSeeAlso,
     * {@literal @XmlRegistry}, etc.) for a given set of JavaClasses, then complete
     * building all of the required TypeInfo objects. This method
     * is typically called after init and preBuildTypeInfo have
     * been called.
     *
     * @return updated array of JavaClasses, made up of the original classes
     * plus any additional ones
     */
    public JavaClass[] postBuildTypeInfo(JavaClass[] javaClasses) {
        if (javaClasses.length == 0) {
            return javaClasses;
        }
        List<JavaClass> originalList = Arrays.asList(javaClasses);
        // create type info instances for any additional classes
        javaClasses = processAdditionalClasses(javaClasses);
        preBuildTypeInfo(javaClasses);
        buildTypeInfo(javaClasses);
        updateGlobalElements(javaClasses);
        if(javaClasses.length > originalList.size()) {
            List<JavaClass> newClasses = new ArrayList<JavaClass>(javaClasses.length - originalList.size());
            for(JavaClass next:javaClasses) {
                if(!(originalList.contains(next))) {
                    newClasses.add(next);
                }
            }
            postBuildTypeInfo(newClasses.toArray(new JavaClass[newClasses.size()]));
        }
        return javaClasses;
    }

    /**
     * INTERNAL:
     *
     * Complete building TypeInfo objects for a given set of JavaClass
     * instances. This method assumes that init, preBuildTypeInfo, and
     * postBuildTypeInfo have been called.
     *
     */
    private Map<String, TypeInfo> buildTypeInfo(JavaClass[] allClasses) {
        for (JavaClass javaClass : allClasses) {
            if (javaClass == null) {
                continue;
            }

            TypeInfo info = typeInfos.get(javaClass.getQualifiedName());
            if (info == null || info.isPostBuilt()) {
                continue;
            }
            info.setPostBuilt(true);

            // handle factory methods
            processFactoryMethods(javaClass, info);

            PackageInfo packageInfo = getPackageInfoForPackage(javaClass);

            XMLNameTransformer transformer = info.getXmlNameTransformer();
            if(transformer == TypeInfo.DEFAULT_NAME_TRANSFORMER){
                XMLNameTransformer nsInfoXmlNameTransformer = packageInfo.getXmlNameTransformer();

                if (nsInfoXmlNameTransformer != null) {
                    info.setXmlNameTransformer(nsInfoXmlNameTransformer);
                } else if (helper.isAnnotationPresent(javaClass, XmlNameTransformer.class)) {
                    XmlNameTransformer xmlNameTransformer = (XmlNameTransformer) helper.getAnnotation(javaClass, XmlNameTransformer.class);
                    Class nameTransformerClass = xmlNameTransformer.value();
                    try {
                        info.setXmlNameTransformer((XMLNameTransformer) nameTransformerClass.getConstructor().newInstance());
                    } catch (ReflectiveOperationException ex) {
                        throw JAXBException.exceptionWithNameTransformerClass(nameTransformerClass.getName(), ex);
                    }
                } else if (helper.isAnnotationPresent(javaClass.getPackage(), XmlNameTransformer.class)) {
                    XmlNameTransformer xmlNameTransformer = (XmlNameTransformer) helper.getAnnotation(javaClass.getPackage(), XmlNameTransformer.class);
                    Class nameTransformerClass = xmlNameTransformer.value();
                    try {
                        info.setXmlNameTransformer((XMLNameTransformer) nameTransformerClass.getConstructor().newInstance());
                    } catch (ReflectiveOperationException ex) {
                        throw JAXBException.exceptionWithNameTransformerClass(nameTransformerClass.getName(), ex);
                    }
                }
            }

            // handle @XmlAccessorType
            postProcessXmlAccessorType(info, packageInfo);

            // handle @XmlType
            postProcessXmlType(javaClass, info, packageInfo);

            // handle @XmlEnum
            if (info.isEnumerationType()) {
                addEnumTypeInfo(javaClass, ((EnumTypeInfo) info));
                continue;
            }

            // process schema type name
            processTypeQName(javaClass, info, packageInfo.getNamespaceInfo());

            // handle superclass if necessary
            JavaClass superClass = javaClass.getSuperclass();
            processPropertiesSuperClass(javaClass, info);
            processReferencedClass(superClass);

            // add properties
            info.setProperties(getPropertiesForClass(javaClass, info));

            // process properties
            processTypeInfoProperties(javaClass, info);

            // handle @XmlAccessorOrder
            postProcessXmlAccessorOrder(info, packageInfo);

            validatePropOrderForInfo(info);
        }
        return typeInfos;
    }

    private TypeInfo processReferencedClass(JavaClass referencedClass){
        if (shouldGenerateTypeInfo(referencedClass)) {
            String qName = referencedClass.getQualifiedName();
            TypeInfo existingInfo = typeInfos.get(qName);
            if (existingInfo == null || !existingInfo.isPreBuilt()) {
                PackageInfo pInfo = getPackageInfoForPackage(referencedClass);
                JavaClass adapterClass = pInfo.getPackageLevelAdaptersByClass().get(qName);
                if (adapterClass == null) {
                    CompilerHelper.addClassToClassLoader(referencedClass, helper.getClassLoader());
                    JavaClass[] jClassArray = new JavaClass[] { referencedClass };
                    buildNewTypeInfo(jClassArray);
                }
                return typeInfos.get(qName);
            } else {
                if (!existingInfo.isPostBuilt()) {
                    PackageInfo pInfo = getPackageInfoForPackage(referencedClass);
                    JavaClass adapterClass = pInfo.getPackageLevelAdaptersByClass().get(qName);
                    if (adapterClass == null) {
                        CompilerHelper.addClassToClassLoader(referencedClass, helper.getClassLoader());
                        JavaClass[] javaClasses = new JavaClass[] { referencedClass };
                        javaClasses = postBuildTypeInfo(javaClasses);
                        for(JavaClass next:javaClasses) {
                            processPropertyTypes(next);
                        }
                    }
                }
                return existingInfo;
            }
        }
        return null;
    }

    /*
    * Get virtual property and XmlID information from parent and set it on info if available
     */
    public void processPropertiesSuperClass(JavaClass cls, TypeInfo info) {
        JavaClass superClass = cls.getSuperclass();
        if (superClass == null) {
            return;
        }
        TypeInfo superClassInfo = this.typeInfos.get(superClass.getQualifiedName());
        if(superClassInfo != null) {
            processPropertiesSuperClass(superClass, superClassInfo);
            classesToProcessPropertyTypes.add(superClass);
            if(superClassInfo.getXmlVirtualAccessMethods() != null && info.getXmlVirtualAccessMethods() == null) {
                info.setXmlVirtualAccessMethods(superClassInfo.getXmlVirtualAccessMethods());
            }
            if(superClassInfo.isIDSet()){
                info.setIDProperty(superClassInfo.getIDProperty());
            }
        }
    }

    /**
     * Perform any final generation and/or validation operations on TypeInfo
     * properties.
     *
     */
    public void finalizeProperties() {

        for (TypeInfo tInfo: getTypeInfos().values()) {
            // don't need to validate props on a transient class at this point
            if (tInfo.isTransient()) {
                continue;
            }
            JavaClass jClass = tInfo.getJavaClass();
            String[] propOrder = tInfo.getPropOrder();
            boolean hasPropOrder = propOrder.length > 0 && !(propOrder.length == 1 && propOrder[0].equals(Constants.EMPTY_STRING));
            // If a property is marked transient, ensure it doesn't exist in the propOrder
            List<String> propOrderList = Arrays.asList(tInfo.getPropOrder());
            List<Property> propsList = tInfo.getPropertyList();
            for (Property p : propsList) {
                if (p.isTransient() && propOrderList.contains(p.getPropertyName())) {
                    throw JAXBException.transientInProporder(p.getPropertyName(), tInfo.getJavaClassName());
                }
                if (hasPropOrder && !p.isAttribute() && !p.isTransient() && !p.isInverseReference()) {
                    if (!propOrderList.contains(p.getPropertyName())) {
                        throw JAXBException.missingPropertyInPropOrder(p.getPropertyName(), tInfo.getJavaClassName());
                    }
                }
            }

            if (!jClass.isInterface() && !tInfo.isEnumerationType() && !jClass.isAbstract()) {
                if (tInfo.getFactoryMethodName() == null && tInfo.getObjectFactoryClassName() == null) {
                    JavaConstructor zeroArgConstructor = jClass.getDeclaredConstructor(new JavaClass[] {});
                    if (zeroArgConstructor == null) {
                        if (tInfo.isSetXmlJavaTypeAdapter()) {
                            tInfo.setTransient(true);
                        } else {
                            if(!referencedByTransformer.contains(jClass.getName())){
                                throw org.eclipse.persistence.exceptions.JAXBException.factoryMethodOrConstructorRequired(jClass.getName());
                            }
                        }
                    }
                }
            }
            // validate XmlValue
            if (tInfo.getXmlValueProperty() != null) {
                validateXmlValueFieldOrProperty(jClass, tInfo.getXmlValueProperty());
            }

            // Keep a list of "any" properties to verify if multiples exist
            // that they have different element wrappers
            List<Property> anyElementProperties = new ArrayList<Property>();

            for (Property property : tInfo.getPropertyList()) {
                // Check that @XmlAttribute references a Java type that maps to text in XML
                if (property.isAttribute()) {
                    validateXmlAttributeFieldOrProperty(tInfo, property);
                }
                JavaClass propertyClass = property.getActualType();

                if (property.isChoice()) {
                    Collection<Property> choiceProps = property.getChoiceProperties();
                    for (Property nextChoiceProp : choiceProps) {
                        JavaClass nextChoicePropTypeClass = nextChoiceProp.getActualType();
                        TypeInfo targetInfo = typeInfos.get(nextChoicePropTypeClass.getQualifiedName());
                        finalizeProperty(property, targetInfo, nextChoicePropTypeClass, jClass);
                    }
                } else {
                    TypeInfo targetInfo = typeInfos.get(propertyClass.getQualifiedName());
                    finalizeProperty(property, targetInfo, propertyClass, jClass);
                }

                // only one XmlValue is allowed per class, and if there is one
                // only XmlAttributes are allowed
                if (tInfo.isSetXmlValueProperty()) {
                    if (property.isXmlValue() && !(tInfo.getXmlValueProperty().getPropertyName().equals(property.getPropertyName()))) {
                        throw JAXBException.xmlValueAlreadySet(property.getPropertyName(), tInfo.getXmlValueProperty().getPropertyName(), jClass.getName());
                    }
                    if (!property.isXmlValue() && !property.isAttribute() && !property.isInverseReference() && !property.isTransient()) {
                        throw JAXBException.propertyOrFieldShouldBeAnAttribute(property.getPropertyName(), jClass.getName());
                    }
                }


                // handle XmlElementRef(s) - validate and build the required
                // ElementDeclaration object
                if (property.isReference()) {
                    processReferenceProperty(property, tInfo, jClass);
                }

                if (property.isSwaAttachmentRef() && !this.hasSwaRef) {
                    this.hasSwaRef = true;
                }

                if (property.isXmlId()) {
                    // there can only be one XmlID per type info
                    if (tInfo.getIDProperty() != null && !(tInfo.getIDProperty().getPropertyName().equals(property.getPropertyName()))) {
                        throw JAXBException.idAlreadySet(property.getPropertyName(), tInfo.getIDProperty().getPropertyName(), jClass.getName());
                    }

                    // XmlID property should be of java.lang.String type
                    validateXmlIdStringType(property);
                }

                // there can only be one XmlAnyAttribute per type info
                if (property.isAnyAttribute() && tInfo.isSetAnyAttributePropertyName() && !(tInfo.getAnyAttributePropertyName().equals(property.getPropertyName()))) {
                    throw JAXBException.multipleAnyAttributeMapping(jClass.getName());
                }
                // there can only be one XmlAnyElement per type info
                if (property.isAny()) {
                    if(!anyElementProperties.isEmpty()) {
                        for(Property nextAny:anyElementProperties) {
                            if(!property.isSetXmlElementWrapper() && !nextAny.isSetXmlElementWrapper()) {
                                throw JAXBException.xmlAnyElementAlreadySet(property.getPropertyName(), nextAny.getPropertyName(), jClass.getName());
                            }
                            org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper wrapper = property.getXmlElementWrapper();
                            org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper targetWrapper = nextAny.getXmlElementWrapper();
                            if(wrapper != null && targetWrapper != null) {
                                if(wrapper.getName().equals(targetWrapper.getName()) && wrapper.getNamespace().equals(targetWrapper.getNamespace())) {
                                    throw JAXBException.xmlAnyElementAlreadySet(property.getPropertyName(), nextAny.getPropertyName(), jClass.getName());
                                }
                            }
                        }
                    }
                    anyElementProperties.add(property);
                }
                // an XmlAttachmentRef can only appear on a DataHandler property
                if (property.isSwaAttachmentRef() && !areEquals(property.getActualType(), JAVAX_ACTIVATION_DATAHANDLER)) {
                    throw JAXBException.invalidAttributeRef(property.getPropertyName(), jClass.getQualifiedName());
                }
                // an XmlElementWrapper can only appear on a Collection or Array
                if (property.getXmlElementWrapper() != null) {
                    if (!helper.isCollectionType(property.getType()) && !property.getType().isArray() && !helper.isMapType(property.getType())) {
                        throw JAXBException.invalidElementWrapper(property.getPropertyName());
                    }
                }

                // handle XmlTransformation - validate transformer class/method
                if (property.isXmlTransformation()) {
                    validateXmlTransformationProperty(property);
                }
                // validate XmlJoinNodes
                if (property.isSetXmlJoinNodes()) {
                    TypeInfo targetInfo = typeInfos.get(propertyClass.getQualifiedName());

                    // the target class must have an associated TypeInfo
                    if (targetInfo == null) {
                        throw JAXBException.invalidXmlJoinNodeReferencedClass(property.getPropertyName(), propertyClass.getQualifiedName());
                    }
                    // validate each referencedXmlPath - target TypeInfo should
                    // have XmlID/XmlKey property with matching XmlPath
                    if (targetInfo.getIDProperty() == null && targetInfo.getXmlKeyProperties() == null) {
                        throw JAXBException.noKeyOrIDPropertyOnJoinTarget(jClass.getQualifiedName(), property.getPropertyName(), propertyClass.getQualifiedName());
                    }
                }
            }
        }
    }

    private void validateXmlIdStringType(Property property) {
        if (!"java.lang.String".equals(property.getActualType().getQualifiedName()) && !MOXySystemProperties.xmlIdExtension && !helper.isAnnotationPresent(property.getElement(), XmlIDExtension.class) && !property.isXmlIdExtension()) {
            throw JAXBException.invalidId(property.getPropertyName());
        }
    }

    private void finalizeProperty(Property property, TypeInfo targetInfo, JavaClass typeClass, JavaClass jClass){
        if (targetInfo != null && targetInfo.isTransient() && property.getXmlElements() == null) {
            property.setTransientType(true);
        }

        // validate XmlIDREF
        if (property.isXmlIdRef()) {
            // the target class must have an associated TypeInfo unless
            // it is Object
            if (targetInfo == null && !typeClass.getQualifiedName().equals(JAVA_LANG_OBJECT)) {
                throw JAXBException.invalidIDREFClass(jClass.getQualifiedName(), property.getPropertyName(), typeClass.getQualifiedName());
            }
            // if the property is an XmlIDREF, the target must have an
            // XmlID set
            if (targetInfo != null && targetInfo.getIDProperty() == null && !preCheckXmlID(typeClass, targetInfo)) {
                throw JAXBException.invalidIdRef(property.getPropertyName(), typeClass.getQualifiedName());
            }
        }
    }

    /**
     * Process a given TypeInfo instance's properties.
     *
     */
    private void processTypeInfoProperties(JavaClass javaClass, TypeInfo info) {
        List<Property> properties = info.getPropertyList();
        for (Property property : properties) {
            // handle @XmlID
            processXmlID(property, javaClass, info);

            // handle @XmlIDREF - validate these properties after processing of
            // all types is completed
            processXmlIDREF(property);

            if (property.isMap()){
                processReferencedClass(property.getKeyType());
                processReferencedClass(property.getActualValueType());
            }
        }
    }

    void processPropertyTypes(JavaClass[] classes) {
        for (JavaClass next : classes) {
            processPropertyTypes(next);
            classesToProcessPropertyTypes.remove(next);
        }
        for (int i =0; i< classesToProcessPropertyTypes.size(); i++) { // throws cme when using foreach
            JavaClass next = classesToProcessPropertyTypes.get(i);
            processPropertyTypes(next);
        }
    }

    private void processPropertyTypes(JavaClass next){

        TypeInfo info = getTypeInfos().get(next.getQualifiedName());
        if (info != null) {
            for (Property property : info.getPropertyList()) {
                if (property.isXmlLocation())
                    info.setLocationAware(true);
                if (property.isTransient())
                    continue;

                JavaClass type = property.getActualType();
                if (property.isReference()) {
                    processReferencePropertyTypes(property, info, next);
                }
                if (property.isChoice()) {
                    processChoiceProperty(property, info, next, type);
                    for (Property choiceProp : property.getChoiceProperties()) {
                        type = choiceProp.getActualType();
                        processReferencedClass(type);
                    }
                } else {
                    processReferencedClass(type);
                }
            }
        }

    }

    /**
     * Process any additional classes, such as inner classes, @XmlRegistry or
     * from @XmlSeeAlso.
     *
     */
    private JavaClass[] processAdditionalClasses(JavaClass[] classes) {
        ArrayList<JavaClass> extraClasses = new ArrayList<JavaClass>();
        ArrayList<JavaClass> classesToProcess = new ArrayList<JavaClass>();
        for (JavaClass jClass : classes) {
            List<TypeMappingInfo> infos = this.javaClassToTypeMappingInfos.get(jClass);
            if(infos != null && infos.size() > 0) {
                for(TypeMappingInfo next:infos) {
                    processAdditionalClasses(jClass, next, extraClasses, classesToProcess);
                }
            } else {
                processAdditionalClasses(jClass, null, extraClasses, classesToProcess);
            }
        }
        // process @XmlRegistry, @XmlSeeAlso and inner classes
        for (JavaClass javaClass : extraClasses) {
            processClass(javaClass, classesToProcess);
        }

        return classesToProcess.toArray(new JavaClass[classesToProcess.size()]);
    }

    private void processAdditionalClasses(JavaClass cls, TypeMappingInfo tmi, ArrayList<JavaClass> extraClasses, ArrayList<JavaClass> classesToProcess) {
        Class xmlElementType = null;
        JavaClass javaClass = cls;
        if (tmi != null) {
            Class adapterClass = this.typeMappingInfoToAdapterClasses.get(tmi);
            if (adapterClass != null) {
                JavaClass adapterJavaClass = helper.getJavaClass(adapterClass);
                JavaClass newType = helper.getJavaClass(Object.class);

                // look for marshal method
                for (Object nextMethod : adapterJavaClass.getDeclaredMethods()) {
                    JavaMethod method = (JavaMethod) nextMethod;
                    if (method.getName().equals("marshal")) {
                        JavaClass returnType = method.getReturnType();
                        if (!returnType.getQualifiedName().equals(newType.getQualifiedName())) {
                            newType = returnType;
                            break;
                        }
                    }
                }
                if (!helper.isBuiltInJavaType(javaClass)) {
                    extraClasses.add(javaClass);
                }
                javaClass = newType;
            }
            java.lang.annotation.Annotation[] annotations = getAnnotations(tmi);
            if (annotations != null) {
                for (Annotation nextAnnotation : annotations) {
                    if (nextAnnotation != null && nextAnnotation instanceof XmlElement) {
                        XmlElement javaAnnotation = (XmlElement) nextAnnotation;
                        if (javaAnnotation.type() != XmlElement.DEFAULT.class) {
                            xmlElementType = javaAnnotation.type();
                        }
                    }
                }
            }
        }

        if (areEquals(javaClass, byte[].class) || areEquals(javaClass, JAVAX_ACTIVATION_DATAHANDLER) || areEquals(javaClass, Source.class) || areEquals(javaClass, Image.class) || areEquals(javaClass, JAVAX_MAIL_INTERNET_MIMEMULTIPART)) {
            if (tmi == null || tmi.getXmlTagName() == null) {
                ElementDeclaration declaration = new ElementDeclaration(null, javaClass, javaClass.getQualifiedName(), false, XmlElementDecl.GLOBAL.class);
                declaration.setTypeMappingInfo(tmi);
                this.localElements.add(declaration);
            }
        } else if (javaClass.isArray()) {
            if (!helper.isBuiltInJavaType(javaClass.getComponentType())) {
                extraClasses.add(javaClass.getComponentType());
            }
            Class generatedClass;
            if (null == tmi) {
                generatedClass = arrayClassesToGeneratedClasses.get(javaClass.getName());
            } else {
                generatedClass = CompilerHelper.getExisitingGeneratedClass(tmi, typeMappingInfosToGeneratedClasses, typeMappingInfoToAdapterClasses, helper.getClassLoader());
            }
            if (generatedClass == null) {
                generatedClass = generateWrapperForArrayClass(javaClass, tmi, xmlElementType, extraClasses);
                extraClasses.add(helper.getJavaClass(generatedClass));
                arrayClassesToGeneratedClasses.put(javaClass.getName(), generatedClass);
            }
            generatedClassesToArrayClasses.put(generatedClass, javaClass);
            typeMappingInfosToGeneratedClasses.put(tmi, generatedClass);

        } else if (helper.isCollectionType(javaClass)) {
            JavaClass componentClass;
            Collection args = javaClass.getActualTypeArguments();
            if (!args.isEmpty()) {
                componentClass = (JavaClass) args.iterator().next();
                if (!componentClass.isPrimitive()) {
                    extraClasses.add(componentClass);
                }
            } else {
                componentClass = helper.getJavaClass(Object.class);
            }

            Class generatedClass = CompilerHelper.getExisitingGeneratedClass(tmi, typeMappingInfosToGeneratedClasses, typeMappingInfoToAdapterClasses, helper.getClassLoader());
            if (generatedClass == null) {
                generatedClass = generateCollectionValue(javaClass, tmi, xmlElementType, extraClasses);
                extraClasses.add(helper.getJavaClass(generatedClass));
            }
            typeMappingInfosToGeneratedClasses.put(tmi, generatedClass);
        } else if (helper.isMapType(javaClass)) {
            JavaClass keyClass;
            JavaClass valueClass;
            Collection args = javaClass.getActualTypeArguments();
            Iterator argsIter = args.iterator();
            if (!args.isEmpty()) {
                keyClass = (JavaClass) argsIter.next();
                if (!helper.isBuiltInJavaType(keyClass)) {
                    extraClasses.add(keyClass);
                }
                valueClass = (JavaClass) argsIter.next();
                if (!helper.isBuiltInJavaType(valueClass)) {
                    extraClasses.add(valueClass);
                }
            } else {
                keyClass = helper.getJavaClass(Object.class);
                valueClass = helper.getJavaClass(Object.class);
            }

            Class generatedClass = CompilerHelper.getExisitingGeneratedClass(tmi, typeMappingInfosToGeneratedClasses, typeMappingInfoToAdapterClasses, helper.getClassLoader());
            if (generatedClass == null) {
                generatedClass = generateWrapperForMapClass(javaClass, keyClass, valueClass, tmi);
                extraClasses.add(helper.getJavaClass(generatedClass));
            }
            typeMappingInfosToGeneratedClasses.put(tmi, generatedClass);
        } else {
            // process @XmlRegistry, @XmlSeeAlso and inner classes
            processClass(javaClass, classesToProcess);
        }
    }

    /**
     * Adds additional classes to the given List, from inner classes,
     *
     * See @XmlRegistry or @XmlSeeAlso.
     *
     */
    private void processClass(JavaClass javaClass, ArrayList<JavaClass> classesToProcess) {
        if (shouldGenerateTypeInfo(javaClass)) {
            if (isXmlRegistry(javaClass)) {
                this.processObjectFactory(javaClass, classesToProcess);
            } else {
                classesToProcess.add(javaClass);
                // handle @XmlSeeAlso
                TypeInfo info = typeInfos.get(javaClass.getQualifiedName());
                if (info != null && info.isSetXmlSeeAlso()) {
                    for (String jClassName : info.getXmlSeeAlso()) {
                        classesToProcess.add(helper.getJavaClass(jClassName));
                    }
                }
            }
        }
    }

    /**
     * Process an @XmlSeeAlso annotation. TypeInfo instances will be created for
     * each class listed.
     *
     */
    private void processXmlSeeAlso(JavaClass javaClass, TypeInfo info) {
        // reflectively load @XmlSeeAlso class to avoid dependency
        Class xmlSeeAlsoClass = null;
        Method valueMethod = null;
        try {
            xmlSeeAlsoClass = PrivilegedAccessHelper.getClassForName("jakarta.xml.bind.annotation.XmlSeeAlso", false, helper.getClassLoader());
            valueMethod = PrivilegedAccessHelper.getDeclaredMethod(xmlSeeAlsoClass, "value", new Class[] {});
        } catch (ClassNotFoundException ex) {
            // Ignore this exception. If SeeAlso isn't available, don't try to
            // process
        } catch (NoSuchMethodException ex) {
        }
        if (xmlSeeAlsoClass != null && helper.isAnnotationPresent(javaClass, xmlSeeAlsoClass)) {
            Object seeAlso = helper.getAnnotation(javaClass, xmlSeeAlsoClass);
            Class[] values = null;
            try {
                values = PrivilegedAccessHelper.invokeMethod(valueMethod, seeAlso, new Object[] {});
            } catch (Exception ex) {
            }

            if (values != null) {
                List<String> seeAlsoClassNames = new ArrayList<String>();
                for (Class next : values) {
                    seeAlsoClassNames.add(next.getName());
                }
                info.setXmlSeeAlso(seeAlsoClassNames);
            }
        }
    }

    /**
     * Process any factory methods.
     *
     */
    private void processFactoryMethods(JavaClass javaClass, TypeInfo info) {
        JavaMethod factoryMethod = this.factoryMethods.get(javaClass.getRawName());
        if (factoryMethod != null) {
            // set up factory method info for mappings.
            info.setFactoryMethodName(factoryMethod.getName());
            info.setObjectFactoryClassName(factoryMethod.getOwningClass().getQualifiedName());
            JavaClass[] paramTypes = factoryMethod.getParameterTypes();
            if (paramTypes != null && paramTypes.length > 0) {
                String[] paramTypeNames = new String[paramTypes.length];
                for (int i = 0; i < paramTypes.length; i++) {
                    processReferencedClass(paramTypes[i]);
                    paramTypeNames[i] = paramTypes[i].getQualifiedName();
                }
                info.setFactoryMethodParamTypes(paramTypeNames);
            }
        }
    }

    /**
     * Process any package-level @XmlJavaTypeAdapters.
     *
     */
    private void processPackageLevelAdapters(JavaClass javaClass, TypeInfo info) {
        JavaPackage pack = javaClass.getPackage();
        if (helper.isAnnotationPresent(pack, XmlJavaTypeAdapters.class)) {
            XmlJavaTypeAdapters adapters = (XmlJavaTypeAdapters) helper.getAnnotation(pack, XmlJavaTypeAdapters.class);
            XmlJavaTypeAdapter[] adapterArray = adapters.value();
            for (XmlJavaTypeAdapter next : adapterArray) {
                processPackageLevelAdapter(next, info);
            }
        }

        if (helper.isAnnotationPresent(pack, XmlJavaTypeAdapter.class)) {
            XmlJavaTypeAdapter adapter = (XmlJavaTypeAdapter) helper.getAnnotation(pack, XmlJavaTypeAdapter.class);
            processPackageLevelAdapter(adapter, info);
        }
    }

    private void processPackageLevelAdapter(XmlJavaTypeAdapter next, TypeInfo info) {
        JavaClass adapterClass = helper.getJavaClass(next.value());
        JavaClass boundType = helper.getJavaClass(next.type());
        if (boundType != null) {
            info.addPackageLevelAdapterClass(adapterClass, boundType);
        } else {
            getLogger().logWarning(JAXBMetadataLogger.INVALID_BOUND_TYPE, new Object[] { null, adapterClass });
        }
    }

    /**
     * Process any class-level @XmlJavaTypeAdapters.
     *
     */
    private void processClassLevelAdapters(JavaClass javaClass, TypeInfo info) {
        if (helper.isAnnotationPresent(javaClass, XmlJavaTypeAdapter.class)) {
            XmlJavaTypeAdapter adapter = (XmlJavaTypeAdapter) helper.getAnnotation(javaClass, XmlJavaTypeAdapter.class);
            String boundType = adapter.type().getName();

            if (boundType == null || boundType.equals("jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT")) {
                boundType = javaClass.getRawName();
            }
            org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
            xja.setValue(adapter.value().getName());
            xja.setType(boundType);

            info.setXmlJavaTypeAdapter(xja);
        }
    }

    /**
     * Process any @XmlSchemaType(s).
     *
     */
    private void processSchemaTypes(JavaClass javaClass, TypeInfo info) {
        JavaPackage pack = javaClass.getPackage();
        if (helper.isAnnotationPresent(pack, XmlSchemaTypes.class)) {
            XmlSchemaTypes types = (XmlSchemaTypes) helper.getAnnotation(pack, XmlSchemaTypes.class);
            XmlSchemaType[] typeArray = types.value();
            for (XmlSchemaType next : typeArray) {
                processSchemaType(next);
            }
        } else if (helper.isAnnotationPresent(pack, XmlSchemaType.class)) {
            processSchemaType((XmlSchemaType) helper.getAnnotation(pack, XmlSchemaType.class));
        }
    }

    /**
     * Process @XmlRootElement annotation on a given JavaClass.
     *
     */
    private void processXmlRootElement(JavaClass javaClass, TypeInfo info) {
        if (helper.isAnnotationPresent(javaClass, XmlRootElement.class)) {
            XmlRootElement rootElemAnnotation = (XmlRootElement) helper.getAnnotation(javaClass, XmlRootElement.class);
            org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement xmlRE = new org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement();
            xmlRE.setName(rootElemAnnotation.name());
            xmlRE.setNamespace(rootElemAnnotation.namespace());
            info.setXmlRootElement(xmlRE);
        }
    }

    /**
     * Process @XmlExtensible annotation on a given JavaClass.
     *
     */
    private void processXmlExtensible(JavaClass javaClass, TypeInfo info) {
        if (helper.isAnnotationPresent(javaClass, XmlVirtualAccessMethods.class)) {
            XmlVirtualAccessMethods extAnnotation = (XmlVirtualAccessMethods) helper.getAnnotation(javaClass, XmlVirtualAccessMethods.class);
            org.eclipse.persistence.jaxb.xmlmodel.XmlVirtualAccessMethods xmlExt = new org.eclipse.persistence.jaxb.xmlmodel.XmlVirtualAccessMethods();
            xmlExt.setGetMethod(extAnnotation.getMethod());
            xmlExt.setSetMethod(extAnnotation.setMethod());
            xmlExt.setSchema(org.eclipse.persistence.jaxb.xmlmodel.XmlVirtualAccessMethodsSchema.valueOf(extAnnotation.schema().toString()));
            info.setXmlVirtualAccessMethods(xmlExt);
        }
    }

    /**
     * Process @XmlType annotation on a given JavaClass and update the TypeInfo
     * for pre-processing. Note that if no @XmlType annotation is present we
     * still create a new XmlType an set it on the TypeInfo.
     *
     */
    private void preProcessXmlType(JavaClass javaClass, TypeInfo info, NamespaceInfo packageNamespace) {
        org.eclipse.persistence.jaxb.xmlmodel.XmlType xmlType = new org.eclipse.persistence.jaxb.xmlmodel.XmlType(); // 14 xmlType=XmlType - default settings: name=null, namespace=null, factoryClass=null, factoryMethod=null, propOrder=null.
        if (helper.isAnnotationPresent(javaClass, XmlType.class)) {
            XmlType typeAnnotation = (XmlType) helper.getAnnotation(javaClass, XmlType.class); // 15 typeAnnotation=com.sun.proxy.$Proxy6"@jakarta.xml.bind.annotation.XmlType(factoryMethod=, name=OneClass, propOrder=[car], factoryClass=class jakarta.xml.bind.annotation.XmlType$DEFAULT, namespace=##default)"
            // set name
            xmlType.setName(typeAnnotation.name()); // 16 XmlType - name="OneClass
            // set namespace
            xmlType.setNamespace(typeAnnotation.namespace()); // 17 xmlType - namespace="##default"
            // set propOrder
            String[] propOrder = typeAnnotation.propOrder(); // 18 propOrder = ["car"]
            // initializes xmlType.propOrder to an empty ArrayList
            if (propOrder != null) {
                xmlType.getPropOrder(); // 19 OK, so this only initializes xmlType.propOrder to an empty ArrayList
            }
            for (String prop : propOrder) {
                xmlType.getPropOrder().add(prop); // 20 - puts "car" into xmlType.propOrder
            }
            // set factoryClass
            Class factoryClass = typeAnnotation.factoryClass(); // 21 factoryClass=java.lang.Class"class jakarta.xml.bind.annotation.XmlType$DEFAULT"
            if (factoryClass == DEFAULT.class) {
                xmlType.setFactoryClass("jakarta.xml.bind.annotation.XmlType.DEFAULT"); // 22
            } else {
                xmlType.setFactoryClass(factoryClass.getCanonicalName());
            }
            // set factoryMethodName
            xmlType.setFactoryMethod(typeAnnotation.factoryMethod()); // 23 defaults to factoryMethod=""
        } else {
            // set defaults
            xmlType.setNamespace(packageNamespace.getNamespace());
        }
        info.setXmlType(xmlType); // 24
    }

    /**
     * Process XmlType for a given TypeInfo. Here we assume that the TypeInfo
     * has an XmlType set - typically via preProcessXmlType or XmlProcessor
     * override.
     *
     */
    private void postProcessXmlType(JavaClass javaClass, TypeInfo info, PackageInfo packageNamespace) {
        // assumes that the TypeInfo has an XmlType set from
        org.eclipse.persistence.jaxb.xmlmodel.XmlType xmlType = info.getXmlType();

        // set/validate factoryClass and factoryMethod
        String factoryClassName = xmlType.getFactoryClass();
        String factoryMethodName = xmlType.getFactoryMethod();

        if (factoryClassName.equals("jakarta.xml.bind.annotation.XmlType.DEFAULT")) {
            if (factoryMethodName != null && !factoryMethodName.equals(EMPTY_STRING)) {
                // factory method applies to the current class - verify method
                // exists
                JavaMethod method = javaClass.getDeclaredMethod(factoryMethodName, new JavaClass[] {});
                if (method == null) {
                    throw org.eclipse.persistence.exceptions.JAXBException.factoryMethodNotDeclared(factoryMethodName, javaClass.getName());
                }
                info.setFactoryMethodName(factoryMethodName);
            }
        } else {
            if (factoryMethodName == null || factoryMethodName.equals(EMPTY_STRING)) {
                throw org.eclipse.persistence.exceptions.JAXBException.factoryClassWithoutFactoryMethod(javaClass.getName());
            }
            info.setObjectFactoryClassName(factoryClassName);
            info.setFactoryMethodName(factoryMethodName);
        }

        // figure out type name
        String typeName = xmlType.getName();
        if (typeName.equals(XMLProcessor.DEFAULT)) {
            try {
                typeName = info.getXmlNameTransformer().transformTypeName(javaClass.getName());
            } catch (Exception ex) {
                throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(javaClass.getName(), info.getXmlNameTransformer().getClass().getName(), ex);
            }
        }
        info.setSchemaTypeName(typeName);

        // set propOrder
        if (xmlType.isSetPropOrder()) {
            List<String> props = xmlType.getPropOrder();
            if (props.size() == 0) {
                info.setPropOrder(new String[0]);
            } else if (props.get(0).equals(EMPTY_STRING)) {
                info.setPropOrder(new String[] { EMPTY_STRING });
            } else {
                info.setPropOrder(xmlType.getPropOrder().toArray(new String[xmlType.getPropOrder().size()]));
            }
        }

        // figure out namespace
        if (xmlType.getNamespace().equals(XMLProcessor.DEFAULT)) {
            info.setClassNamespace(packageNamespace.getNamespace());
        } else {
            info.setClassNamespace(xmlType.getNamespace());
        }
    }

    /**
     * Process @XmlAccessorType annotation on a given JavaClass and update the
     * TypeInfo for pre-processing.
     *
     */
    private void preProcessXmlAccessorType(JavaClass javaClass, TypeInfo info, NamespaceInfo packageNamespace) {
        org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType xmlAccessType;
        if (javaClass.getDeclaredAnnotation(helper.getJavaClass(XmlAccessorType.class)) != null) {
            XmlAccessorType accessorType = (XmlAccessorType) helper.getAnnotation(javaClass, XmlAccessorType.class);
            xmlAccessType = org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType.fromValue(accessorType.value().name());
            info.setXmlAccessType(xmlAccessType);
        }
    }

    /**
     * Post process XmlAccessorType. In some cases, such as @XmlSeeAlso classes,
     * the access type may not have been set
     *
     */
    private void postProcessXmlAccessorType(TypeInfo info, PackageInfo packageNamespace) {
        if (!info.isSetXmlAccessType()) {
            // Check for super class
            JavaClass next = helper.getJavaClass(info.getJavaClassName()).getSuperclass();
            while (next != null && !(next.getName().equals(JAVA_LANG_OBJECT))) {
                processReferencedClass(next);
                TypeInfo parentInfo = this.typeInfos.get(next.getName());
                if (parentInfo != null && parentInfo.isSetXmlAccessType()) {
                    info.setXmlAccessType(parentInfo.getXmlAccessType());
                    break;
                }
                next = next.getSuperclass();
            }
            // use value in package-info.java as last resort - will default if
            // not set
            if(!(info.isSetXmlAccessType())) {
                info.setXmlAccessType(org.eclipse.persistence.jaxb.xmlmodel.XmlAccessType.fromValue(packageNamespace.getAccessType().name()));
            }
        }
    }

    /**
     * Process package and class @XmlAccessorOrder. Class level annotation
     * overrides a package level annotation.
     *
     */
    private void preProcessXmlAccessorOrder(JavaClass javaClass, TypeInfo info, NamespaceInfo packageNamespace) {
        XmlAccessorOrder order = null;
        // class level annotation overrides package level annotation
        if (helper.isAnnotationPresent(javaClass, XmlAccessorOrder.class)) {
            order = (XmlAccessorOrder) helper.getAnnotation(javaClass, XmlAccessorOrder.class);
            info.setXmlAccessOrder(XmlAccessOrder.fromValue(order.value().name()));
        }
    }

    /**
     * Post process XmlAccessorOrder. This method assumes that the given
     * TypeInfo has already had its order set (via annotations in
     * preProcessXmlAccessorOrder or via xml metadata override in XMLProcessor).
     *
     */
    private void postProcessXmlAccessorOrder(TypeInfo info, PackageInfo packageNamespace) {
        if (!info.isSetXmlAccessOrder()) {
            // use value in package-info.java as last resort - will default if
            // not set
            info.setXmlAccessOrder(org.eclipse.persistence.jaxb.xmlmodel.XmlAccessOrder.fromValue(packageNamespace.getAccessOrder().name()));
        }
        info.orderProperties();
    }

    /**
     * Process @XmlElement annotation on a given property.
     *
     */
    private void processXmlElement(Property property, TypeInfo info) {

        if (helper.isAnnotationPresent(property.getElement(), XmlElementNillable.class)) {
            XmlElementNillable elementNillable = (XmlElementNillable) helper.getAnnotation(property.getElement(), XmlElementNillable.class);
            property.setNillable(elementNillable.nillable());
        } else if (info.isXmlElementNillable()) {
            property.setNillable(true);
        }

        if (helper.isAnnotationPresent(property.getElement(), XmlElement.class)) {
            XmlElement element = (XmlElement) helper.getAnnotation(property.getElement(), XmlElement.class);
            property.setIsRequired(element.required());
            property.setNillable(element.nillable());
            if (element.type() != XmlElement.DEFAULT.class && !(property.isSwaAttachmentRef())) {
                property.setOriginalType(property.getType());
                if (helper.isCollectionType(property.getType()) || property.getType().isArray()) {
                    property.setGenericType(helper.getJavaClass(element.type()));
                } else {
                    JavaClass originalType = property.getType();
                    JavaClass newType =helper.getJavaClass(element.type());
                    if(!originalType.getName().equals(newType.getName())){
                        property.setTyped(true);
                        property.setSchemaType((QName) helper.getXMLToJavaTypeMap().get(newType.getName()));
                    }
                    property.setType(newType);
                }
                property.setHasXmlElementType(true);
            }
            // handle default value
            if (!element.defaultValue().equals(ELEMENT_DECL_DEFAULT)) {
                property.setDefaultValue(element.defaultValue());
            }

            if (facets) addFacets(property);
        }
    }

    /**
     * @since 2.6
     * @author Marcel Valovy
     * @param property property for which facets will be generated
     */
    private void addFacets(Property property) {
        final JavaHasAnnotations element = property.getElement();
        if (helper.isAnnotationPresent(element, DecimalMin.class)) {
            DecimalMin a = (DecimalMin) helper.getAnnotation(element, DecimalMin.class);
            DecimalMinFacet facet = new DecimalMinFacet(a.value(), a.inclusive());
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, DecimalMax.class)) {
            DecimalMax a = (DecimalMax) helper.getAnnotation(element, DecimalMax.class);
            DecimalMaxFacet facet = new DecimalMaxFacet(a.value(), a.inclusive());
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, Digits.class)) {
            Digits a = (Digits) helper.getAnnotation(element, Digits.class);
            DigitsFacet facet = new DigitsFacet(a.integer(), a.fraction());
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, Max.class)) {
            Max a = (Max) helper.getAnnotation(element, Max.class);
            MaxFacet facet = new MaxFacet(a.value());
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, Min.class)) {
            Min a = (Min) helper.getAnnotation(element, Min.class);
            MinFacet facet = new MinFacet(a.value());
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, NotNull.class)) {
            property.setNotNullAnnotated(true);
        }
        if (helper.isAnnotationPresent(element, Pattern.class)) {
            Pattern a = (Pattern) helper.getAnnotation(element, Pattern.class);
            PatternFacet facet = new PatternFacet(a.regexp(), a.flags());
            property.addFacet(facet);
        }
        /* Example:
            @Pattern.List({
                @Pattern(regexp = "first_expression", message = "first.Pattern.message"),
                @Pattern(regexp = "second_expression", message = "second.Pattern.message"),
                @Pattern(regexp = "third_expression", message = "third.Pattern.message")
        }) */
        if (helper.isAnnotationPresent(element, Pattern.List.class)) {
            Pattern.List a = (Pattern.List) helper.getAnnotation(element, Pattern.List.class);
            PatternListFacet facet = new PatternListFacet(new ArrayList<PatternFacet>());
            for (Pattern pat : a.value()) {
                PatternFacet pf = new PatternFacet(pat.regexp(), pat.flags());
                facet.addPattern(pf);
            }
            property.addFacet(facet);
        }
        if (helper.isAnnotationPresent(element, Size.class)) {
            Size a = (Size) helper.getAnnotation(element, Size.class);
            final int min = a.min();
            final int max = a.max();
            if (min != 0 || max != Integer.MAX_VALUE) { // Fixes generation of an empty facet.
                if ("java.lang.String".equals(property.getType().getName())) { // @Size serves for both length facet and occurs restriction.
                    SizeFacet facet = new SizeFacet(min, max); // For minLength, maxLength.
                    property.addFacet(facet);
                } else { // For minOccurs, maxOccurs.
                    if (min > 0)                 property.setMinOccurs(min); // 0 is default minBoundary.
                    if (max < Integer.MAX_VALUE) property.setMaxOccurs(max); // 2^31 is default maxBoundary.
                }
            }
        }
    }

    /**
     * Process @XmlID annotation on a given property
     *
     */
    private void processXmlID(Property property, JavaClass javaClass, TypeInfo info) {
        if (helper.isAnnotationPresent(property.getElement(), XmlID.class)) {
            property.setIsXmlId(true);
            info.setIDProperty(property);
        }
    }

    /**
     * Process @XmlIDREF on a given property.
     *
     */
    private void processXmlIDREF(Property property) {
        if (helper.isAnnotationPresent(property.getElement(), XmlIDREF.class)) {
            property.setIsXmlIdRef(true);
        }
    }

    /**
     * Process @XmlJavaTypeAdapter on a given property.
     *
     */
    private void processXmlJavaTypeAdapter(Property property, TypeInfo info, JavaClass javaClass) {
        JavaClass adapterClass = null;
        JavaClass ptype = property.getActualType();
        if (helper.isAnnotationPresent(property.getElement(), XmlJavaTypeAdapter.class)) {
            XmlJavaTypeAdapter adapter = (XmlJavaTypeAdapter) helper.getAnnotation(property.getElement(), XmlJavaTypeAdapter.class);
            org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
            xja.setValue(adapter.value().getName());
            xja.setType(adapter.type().getName());
            property.setXmlJavaTypeAdapter(xja);
        } else {
            TypeInfo ptypeInfo = typeInfos.get(ptype.getQualifiedName());
            org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xmlJavaTypeAdapter;
            if (ptypeInfo == null && shouldGenerateTypeInfo(ptype)) {
                if (helper.isAnnotationPresent(ptype, XmlJavaTypeAdapter.class)) {
                    XmlJavaTypeAdapter adapter = (XmlJavaTypeAdapter) helper.getAnnotation(ptype, XmlJavaTypeAdapter.class);
                    org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
                    xja.setValue(adapter.value().getName());
                    /*String boundType = adapter.type().getName();
                    if (boundType == null || boundType.equals("jakarta.xml.bind.annotation.adapters.XmlJavaTypeAdapter.DEFAULT")) {
                        boundType = ptype.getRawName();
                    } value from boundType is not used - fix if you know what it should do. */
                    xja.setType(adapter.type().getName());
                    property.setXmlJavaTypeAdapter(xja);
                }
            }
            if (ptypeInfo != null) {
                if (null != (xmlJavaTypeAdapter = ptypeInfo.getXmlJavaTypeAdapter())) {
                    try {
                        property.setXmlJavaTypeAdapter(xmlJavaTypeAdapter);
                    } catch (JAXBException e) {
                        throw JAXBException.invalidTypeAdapterClass(xmlJavaTypeAdapter.getValue(), javaClass.getName());
                    }
                }
            }
            if(info.hasPackageLevelAdaptersByClass()) {
                if (info.getPackageLevelAdaptersByClass().get(ptype.getQualifiedName()) != null && !property.isSetXmlJavaTypeAdapter()) {
                    adapterClass = info.getPackageLevelAdapterClass(ptype);

                    org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xja = new org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter();
                    xja.setValue(adapterClass.getQualifiedName());
                    xja.setType(ptype.getQualifiedName());
                    property.setXmlJavaTypeAdapter(xja);
                }
            }
        }
    }

    /**
     * Store a QName (if necessary) based on a given TypeInfo's schema type
     * name.
     *
     */
    private void processTypeQName(JavaClass javaClass, TypeInfo info, NamespaceInfo packageNamespace) {
        if(info.isTransient()) {
            return;
        }
        String typeName = info.getSchemaTypeName();
        if (typeName != null && !(EMPTY_STRING.equals(typeName))) {
            QName typeQName = new QName(info.getClassNamespace(), typeName);

            boolean containsQName = typeQNames.contains(typeQName);
            if (containsQName) {
                throw JAXBException.nameCollision(typeQName.getNamespaceURI(), typeQName.getLocalPart());
            } else {
                typeQNames.add(typeQName);
            }
        }
    }

    public boolean shouldGenerateTypeInfo(JavaClass javaClass) {
        if (javaClass == null || javaClass.isPrimitive() || javaClass.isAnnotation() || ORG_W3C_DOM.equals(javaClass.getPackageName())) {
            return false;
        }
        if (userDefinedSchemaTypes.get(javaClass.getQualifiedName()) != null) {
            return false;
        }
        if (javaClass.isArray()) {
            String javaClassName = javaClass.getName();
            if (!(javaClassName.equals(CoreClassConstants.APBYTE.getName()))&& !(javaClassName.equals(CoreClassConstants.ABYTE.getName()))) {
                return true;
            }
        }
        if (helper.isBuiltInJavaType(javaClass) && !javaClass.isEnum()) {
            return false;
        }
        if (helper.isCollectionType(javaClass) || helper.isMapType(javaClass)) {
            return false;
        }
        return true;
    }

    public ArrayList<Property> getPropertiesForClass(JavaClass cls, TypeInfo info) {
        ArrayList<Property> returnList = new ArrayList<Property>();

        if (!info.isTransient()) {
            JavaClass superClass = cls.getSuperclass();
            if (null != superClass) {
                TypeInfo superClassInfo = typeInfos.get(superClass.getQualifiedName());
                ArrayList<Property> superClassProperties;
                while (superClassInfo != null && superClassInfo.isTransient()) {
                    if (info.getXmlAccessType() == XmlAccessType.FIELD) {
                        superClassProperties = getFieldPropertiesForClass(superClass, superClassInfo, false);
                    } else if (info.getXmlAccessType() == XmlAccessType.PROPERTY) {
                        superClassProperties = getPropertyPropertiesForClass(superClass, superClassInfo, false);
                    } else if (info.getXmlAccessType() == XmlAccessType.PUBLIC_MEMBER) {
                        superClassProperties = getPublicMemberPropertiesForClass(superClass, superClassInfo);
                    } else {
                        superClassProperties = getNoAccessTypePropertiesForClass(superClass, superClassInfo);
                    }
                    superClass = superClass.getSuperclass();
                    superClassInfo = typeInfos.get(superClass.getQualifiedName());
                    for(Property next:superClassProperties) {
                        next.setIsSuperClassProperty(true);
                    }
                    returnList.addAll(0, superClassProperties);
                }
            }
        }

        if (info.isTransient()) {
            returnList.addAll(getNoAccessTypePropertiesForClass(cls, info));
        } else if (info.getXmlAccessType() == XmlAccessType.FIELD) {
            returnList.addAll(getFieldPropertiesForClass(cls, info, false));
            returnList.addAll(getPropertyPropertiesForClass(cls, info, false, true));
        } else if (info.getXmlAccessType() == XmlAccessType.PROPERTY) {
            returnList.addAll(getFieldPropertiesForClass(cls, info, false, true));
            returnList.addAll(getPropertyPropertiesForClass(cls, info, false));
        } else if (info.getXmlAccessType() == XmlAccessType.PUBLIC_MEMBER) {
            returnList.addAll(getPublicMemberPropertiesForClass(cls, info));
        } else {
            returnList.addAll(getNoAccessTypePropertiesForClass(cls, info));
        }
        return returnList;
    }

    public ArrayList<Property> getFieldPropertiesForClass(JavaClass cls, TypeInfo info, boolean onlyPublic) {
        return getFieldPropertiesForClass(cls, info, onlyPublic, false);
    }

    public ArrayList<Property> getFieldPropertiesForClass(JavaClass cls, TypeInfo info, boolean onlyPublic, boolean onlyExplicit) {
        ArrayList<Property> properties = new ArrayList<Property>();
        if (cls == null) {
            return properties;
        }

        for (JavaField javaField : (Iterable<JavaField>) cls.getDeclaredFields()) {
            Property property = null;
            int modifiers = javaField.getModifiers();

            if (!Modifier.isTransient(modifiers) && ((Modifier.isPublic(javaField.getModifiers()) && onlyPublic) || !onlyPublic || hasJAXBAnnotations(javaField))) {
                if (!Modifier.isStatic(modifiers)) {
                    if ((onlyExplicit && hasJAXBAnnotations(javaField)) || !onlyExplicit) {
                        try {
                            property = buildNewProperty(info, cls, javaField, javaField.getName(), javaField.getResolvedType());
                            properties.add(property);
                        } catch (JAXBException ex) {
                            if (ex.getErrorCode() != JAXBException.INVALID_INTERFACE || !helper.isAnnotationPresent(javaField, XmlTransient.class)) {
                                throw ex;
                            }
                        }
                    }
                } else {
                    try {
                        property = buildNewProperty(info, cls, javaField, javaField.getName(), javaField.getResolvedType());
                        if (helper.isAnnotationPresent(javaField, XmlAttribute.class)) {
                            Object value = ((JavaFieldImpl) javaField).get(null);
                            if (value != null) {
                                String stringValue = XMLConversionManager.getDefaultXMLManager().convertObject(value, String.class, property.getSchemaType());
                                property.setFixedValue(stringValue);
                            }
                        }
                        property.setWriteOnly(true);
                        if (!hasJAXBAnnotations(javaField)) {
                            property.setTransient(true);
                        }
                        properties.add(property);
                    } catch (ClassCastException e) {
                        // do Nothing
                    } catch (IllegalAccessException e) {
                        // do Nothing
                    } catch (JAXBException ex) {
                        if (ex.getErrorCode() != JAXBException.INVALID_INTERFACE || !helper.isAnnotationPresent(javaField, XmlTransient.class)) {
                            throw ex;
                        }
                    }
                }
            }

            if (helper.isAnnotationPresent(javaField, XmlTransient.class)) {
                if (property != null) {
                    property.setTransient(true);
                }
            }
        }
        return properties;
    }

    /*
    * Create a new Property Object and process the annotations that are common
    * to fields and methods
     */
    Property buildNewProperty(TypeInfo info, JavaClass cls, JavaHasAnnotations javaHasAnnotations, String propertyName, JavaClass ptype) {
        Property property = null;
        if (helper.isAnnotationPresent(javaHasAnnotations, XmlElements.class)) {
            property = buildChoiceProperty(javaHasAnnotations);
        } else if (helper.isAnnotationPresent(javaHasAnnotations, XmlElementRef.class) || helper.isAnnotationPresent(javaHasAnnotations, XmlElementRefs.class)) {

            findAndProcessObjectFactory(cls);

            property = buildReferenceProperty(info, javaHasAnnotations, propertyName, ptype);
            if (helper.isAnnotationPresent(javaHasAnnotations, XmlAnyElement.class)) {
                XmlAnyElement anyElement = (XmlAnyElement) helper.getAnnotation(javaHasAnnotations, XmlAnyElement.class);
                property.setIsAny(true);
                if (anyElement.value() != null) {
                    property.setDomHandlerClassName(anyElement.value().getName());
                }
                property.setLax(anyElement.lax());
                info.setAnyElementPropertyName(propertyName);
            }
        } else if (helper.isAnnotationPresent(javaHasAnnotations, XmlAnyElement.class)) {
            findAndProcessObjectFactory(cls);
            XmlAnyElement anyElement = (XmlAnyElement) helper.getAnnotation(javaHasAnnotations, XmlAnyElement.class);
            property = new Property(helper);
            property.setIsAny(true);
            if (anyElement.value() != null) {
                property.setDomHandlerClassName(anyElement.value().getName());
            }
            property.setLax(anyElement.lax());
            info.setAnyElementPropertyName(propertyName);
        } else if (helper.isAnnotationPresent(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlTransformation.class) || helper.isAnnotationPresent(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlReadTransformer.class) || helper.isAnnotationPresent(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlWriteTransformer.class) || helper.isAnnotationPresent(javaHasAnnotations, XmlWriteTransformers.class)) {
            property = buildTransformationProperty(javaHasAnnotations, cls);
        } else {
            property = new Property(helper);
        }
        property.setPropertyName(propertyName);
        property.setElement(javaHasAnnotations);

        // if there is a TypeInfo for ptype check it for transient, otherwise
        // check the class
        if (helper.isCollectionType(ptype)) {
            JavaClass componentType = helper.getJavaClass(Object.class);

            Collection typeArgs =  ptype.getActualTypeArguments();
            if(!typeArgs.isEmpty()) {
                componentType = (JavaClass) typeArgs.iterator().next();
            }
            updatePropertyType(property, ptype, componentType);
        }else{
            updatePropertyType(property, ptype, ptype);
        }

        if(helper.isAnnotationPresent(javaHasAnnotations, XmlVariableNode.class)){
            XmlVariableNode variableNode = (XmlVariableNode) helper.getAnnotation(javaHasAnnotations, XmlVariableNode.class);
            if(variableNode.type() != XmlVariableNode.DEFAULT.class){
                property.setVariableClassName(variableNode.type().getName());

                JavaClass componentType = helper.getJavaClass(variableNode.type());

                if(helper.isCollectionType(ptype)){
                    property.setGenericType(componentType);
                }else{
                    property.setType(componentType);
                }

            }
            if(!variableNode.value().equals("##default")){
                property.setVariableAttributeName(variableNode.value());
            }
            property.setVariableNodeAttribute(variableNode.attribute());
        }


        if((ptype.isArray()  && !areEquals(ptype, byte[].class))  || (helper.isCollectionType(ptype) && !helper.isAnnotationPresent(javaHasAnnotations, XmlList.class)) ){
            property.setNillable(true);
        }
        processPropertyAnnotations(info, cls, javaHasAnnotations, property);

        if (helper.isAnnotationPresent(javaHasAnnotations, XmlPath.class)) {
            XmlPath xmlPath = (XmlPath) helper.getAnnotation(javaHasAnnotations, XmlPath.class);
            property.setXmlPath(xmlPath.value());
            Field tempField = new XMLField(xmlPath.value());
            boolean isAttribute = tempField.getLastXPathFragment().isAttribute();
            property.setIsAttribute(isAttribute);
            // set schema name
            String schemaName = XMLProcessor.getNameFromXPath(xmlPath.value(), property.getPropertyName(), isAttribute);
            QName qName;
            NamespaceInfo nsInfo = getPackageInfoForPackage(cls).getNamespaceInfo();
            if(isAttribute){
                if (nsInfo.isAttributeFormQualified()) {
                    qName = new QName(nsInfo.getNamespace(), schemaName);
                } else {
                    qName = new QName(schemaName);
                }
            }else{
                if (nsInfo.isElementFormQualified()) {
                    qName = new QName(nsInfo.getNamespace(), schemaName);
                } else {
                    qName = new QName(schemaName);
                }
            }
            property.setSchemaName(qName);
            //create properties for any predicates
            XPathFragment fragment = tempField.getXPathFragment();
            String currentPath = "";
            while(fragment != null && !(fragment.nameIsText()) && !(fragment.isAttribute())) {
                if(fragment.getPredicate() != null) {
                    //can't append xpath directly since it will contain the predicate
                    String fragmentPath = fragment.getLocalName();
                    if(fragment.getPrefix() != null && !(Constants.EMPTY_STRING.equals(fragment.getPrefix()))) {
                        fragmentPath = fragment.getPrefix() + ":" + fragmentPath;
                    }
                    currentPath += fragmentPath;
                    String predicatePath = currentPath;
                    TypeInfo targetInfo = info;
                    if(fragment.getNextFragment() == null) {
                        //if this is the last fragment, and there's no text after, then this is
                        //complex. May need to add the attribute property to the target type.
                        processReferencedClass(ptype);
                        TypeInfo predicateTypeInfo = typeInfos.get(ptype.getQualifiedName());
                        if(predicateTypeInfo != null) {
                            targetInfo = predicateTypeInfo;
                            predicatePath = "";
                        }
                    }
                    Property predicateProperty = new Property(helper);
                    predicateProperty.setType(helper.getJavaClass("java.lang.String"));
                    if(predicatePath.length() > 0) {
                        predicatePath += "/";
                    }
                    predicatePath += fragment.getPredicate().getXPathFragment().getXPath();
                    predicateProperty.setXmlPath(predicatePath);
                    predicateProperty.setIsAttribute(true);

                    String predschemaName = XMLProcessor.getNameFromXPath(predicatePath, property.getPropertyName(), true);
                    QName predQname;
                    if (nsInfo.isAttributeFormQualified()) {
                        predQname = new QName(nsInfo.getNamespace(), predschemaName);
                    } else {
                        predQname = new QName(predschemaName);
                    }
                    predicateProperty.setSchemaName(predQname);

                    if(!targetInfo.hasPredicateProperty(predicateProperty)) {
                        targetInfo.getPredicateProperties().add(predicateProperty);
                    }
                } else {
                    currentPath += fragment.getXPath();
                }
                currentPath += "/";
                fragment = fragment.getNextFragment();
            }

        } else {
            property.setSchemaName(getQNameForProperty(property, propertyName, javaHasAnnotations, getPackageInfoForPackage(cls).getNamespaceInfo(), info));
        }

        ptype = property.getActualType();
        if (ptype.isPrimitive()) {
            if (property.getType().isArray() && helper.isAnnotationPresent(javaHasAnnotations, XmlElement.class)) {
                XmlElement elemAnno = (XmlElement) helper.getAnnotation(javaHasAnnotations, XmlElement.class);
                property.setIsRequired(elemAnno.required());
            } else {
                property.setIsRequired(true);
            }
        }

        // apply class level adapters - don't override property level adapter
        if (!property.isSetXmlJavaTypeAdapter()) {
            TypeInfo refClassInfo = getTypeInfos().get(ptype.getQualifiedName());
            if (refClassInfo != null && refClassInfo.isSetXmlJavaTypeAdapter()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter xmlJavaTypeAdapter = null;
                try {
                    xmlJavaTypeAdapter = refClassInfo.getXmlJavaTypeAdapter();
                    property.setXmlJavaTypeAdapter(refClassInfo.getXmlJavaTypeAdapter());
                } catch (JAXBException e) {
                    throw JAXBException.invalidTypeAdapterClass(xmlJavaTypeAdapter.getValue(), cls.getName());
                }
            }
        }

        if(property.isXmlTransformation()){
            referencedByTransformer.add(property.getType().getName());
        }
        return property;
    }


    private void updatePropertyType(Property property, JavaClass ptype, JavaClass componentType){
        TypeInfo componentTypeInfo = typeInfos.get(componentType.getQualifiedName());
        if((componentTypeInfo != null && !componentTypeInfo.isTransient()) || !helper.isAnnotationPresent(componentType, XmlTransient.class)){
            property.setType(ptype);
        }else{
            JavaClass parent = componentType.getSuperclass();
            while (parent != null) {
                if (parent.getName().equals(JAVA_LANG_OBJECT)) {
                    property.setTransientType(true);
                    property.setType(ptype);
                    break;
                }
                // if there is a TypeInfo for parent check it for transient,
                // otherwise check the class
                TypeInfo parentTypeInfo = typeInfos.get(parent.getQualifiedName());
                if ((parentTypeInfo != null && !parentTypeInfo.isTransient()) || !helper.isAnnotationPresent(parent, XmlTransient.class)) {
                    property.setType(parent);
                    break;
                }
                parent = parent.getSuperclass();
            }
        }
    }

    /**
     * Build a new 'choice' property. Here, we flag a new property as a 'choice'
     * and create/set an XmlModel XmlElements object based on the @XmlElements
     * annotation.
     *
     * Validation and building of the XmlElement properties will be done during
     * finalizeProperties in the processChoiceProperty method.
     *
     */
    private Property buildChoiceProperty(JavaHasAnnotations javaHasAnnotations) {
        Property choiceProperty = new Property(helper);
        choiceProperty.setChoice(true);
        boolean isIdRef = helper.isAnnotationPresent(javaHasAnnotations, XmlIDREF.class);
        choiceProperty.setIsXmlIdRef(isIdRef);
        // build an XmlElement to set on the Property
        org.eclipse.persistence.jaxb.xmlmodel.XmlElements xmlElements = new org.eclipse.persistence.jaxb.xmlmodel.XmlElements();
        XmlElement[] elements = ((XmlElements) helper.getAnnotation(javaHasAnnotations, XmlElements.class)).value();
        for (XmlElement next : elements) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlElement xmlElement = new org.eclipse.persistence.jaxb.xmlmodel.XmlElement();
            xmlElement.setDefaultValue(next.defaultValue());
            xmlElement.setName(next.name());
            xmlElement.setNamespace(next.namespace());
            xmlElement.setNillable(next.nillable());
            xmlElement.setRequired(next.required());
            xmlElement.setType(next.type().getName());
            xmlElements.getXmlElement().add(xmlElement);
        }
        choiceProperty.setXmlElements(xmlElements);

        // handle XmlElementsJoinNodes
        if (helper.isAnnotationPresent(javaHasAnnotations, XmlElementsJoinNodes.class)) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes xmlJoinNodes;
            org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode xmlJoinNode;
            List<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes> xmlJoinNodesList = new ArrayList<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes>();
            List<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode> xmlJoinNodeList = null;

            for (XmlJoinNodes xmlJNs : ((XmlElementsJoinNodes) helper.getAnnotation(javaHasAnnotations, XmlElementsJoinNodes.class)).value()) {
                xmlJoinNodeList = new ArrayList<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode>();
                for (XmlJoinNode xmlJN : xmlJNs.value()) {
                    xmlJoinNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode();
                    xmlJoinNode.setXmlPath(xmlJN.xmlPath());
                    xmlJoinNode.setReferencedXmlPath(xmlJN.referencedXmlPath());
                    xmlJoinNodeList.add(xmlJoinNode);
                }
                if (xmlJoinNodeList.size() > 0) {
                    xmlJoinNodes = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes();
                    xmlJoinNodes.setXmlJoinNode(xmlJoinNodeList);
                    xmlJoinNodesList.add(xmlJoinNodes);
                }
            }
            choiceProperty.setXmlJoinNodesList(xmlJoinNodesList);
        }
        return choiceProperty;
    }

    private Property buildTransformationProperty(JavaHasAnnotations javaHasAnnotations, JavaClass cls) {
        Property property = new Property(helper);
        org.eclipse.persistence.oxm.annotations.XmlTransformation transformationAnnotation = (org.eclipse.persistence.oxm.annotations.XmlTransformation) helper.getAnnotation(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlTransformation.class);
        XmlTransformation transformation = new XmlTransformation();
        if (transformationAnnotation != null) {
            transformation.setOptional(transformationAnnotation.optional());
        }

        // Read Transformer
        org.eclipse.persistence.oxm.annotations.XmlReadTransformer readTransformer = (org.eclipse.persistence.oxm.annotations.XmlReadTransformer) helper.getAnnotation(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlReadTransformer.class);
        if (readTransformer != null) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlReadTransformer xmlReadTransformer = new org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlReadTransformer();
            if (!(readTransformer.transformerClass() == AttributeTransformer.class)) {
                xmlReadTransformer.setTransformerClass(readTransformer.transformerClass().getName());
            } else if (!(readTransformer.method().equals(EMPTY_STRING))) {
                xmlReadTransformer.setMethod(readTransformer.method());
            }
            transformation.setXmlReadTransformer(xmlReadTransformer);
        }

        // Handle Write Transformers
        org.eclipse.persistence.oxm.annotations.XmlWriteTransformer[] transformers = null;
        if (helper.isAnnotationPresent(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlWriteTransformer.class)) {
            org.eclipse.persistence.oxm.annotations.XmlWriteTransformer writeTransformer = (org.eclipse.persistence.oxm.annotations.XmlWriteTransformer) helper.getAnnotation(javaHasAnnotations, org.eclipse.persistence.oxm.annotations.XmlWriteTransformer.class);
            transformers = new org.eclipse.persistence.oxm.annotations.XmlWriteTransformer[] { writeTransformer };
        } else if (helper.isAnnotationPresent(javaHasAnnotations, XmlWriteTransformers.class)) {
            XmlWriteTransformers writeTransformers = (XmlWriteTransformers) helper.getAnnotation(javaHasAnnotations, XmlWriteTransformers.class);
            transformers = writeTransformers.value();
        }

        if (transformers != null) {
            for (org.eclipse.persistence.oxm.annotations.XmlWriteTransformer next : transformers) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlWriteTransformer xmlWriteTransformer = new org.eclipse.persistence.jaxb.xmlmodel.XmlTransformation.XmlWriteTransformer();
                if (!(next.transformerClass() == FieldTransformer.class)) {
                    xmlWriteTransformer.setTransformerClass(next.transformerClass().getName());
                } else if (!(next.method().equals(EMPTY_STRING))) {
                    xmlWriteTransformer.setMethod(next.method());
                }
                xmlWriteTransformer.setXmlPath(next.xmlPath());
                transformation.getXmlWriteTransformer().add(xmlWriteTransformer);
            }
        }
        property.setXmlTransformation(transformation);
        property.setIsXmlTransformation(true);
        return property;
    }

    /**
     * Complete creation of a 'choice' property. Here, a Property is created for
     * each XmlElement in the XmlElements list. Validation is performed as well.
     * Each created Property is added to the owning Property's list of choice
     * properties.
     *
     */
    private void processChoiceProperty(Property choiceProperty, TypeInfo info, JavaClass cls, JavaClass propertyType) {
        String propertyName = choiceProperty.getPropertyName();

        // validate XmlElementsXmlJoinNodes (if set)
        if (choiceProperty.isSetXmlJoinNodesList()) {
            // there must be one XmlJoinNodes entry per XmlElement
            if (choiceProperty.getXmlElements().getXmlElement().size() != choiceProperty.getXmlJoinNodesList().size()) {
                throw JAXBException.incorrectNumberOfXmlJoinNodesOnXmlElements(propertyName, cls.getQualifiedName());
            }
        }

        XmlPath[] paths = null;
        if (helper.isAnnotationPresent(choiceProperty.getElement(), XmlPaths.class)) {
            XmlPaths pathAnnotation = (XmlPaths) helper.getAnnotation(choiceProperty.getElement(), XmlPaths.class);
            paths = pathAnnotation.value();
        }
        List<Property> choiceProperties = new ArrayList<Property>();
        for (int i = 0; i < choiceProperty.getXmlElements().getXmlElement().size(); i++) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlElement next = choiceProperty.getXmlElements().getXmlElement().get(i);
            Property choiceProp = new Property(helper);

            String name;
            String namespace;

            choiceProp.setNillable(next.isNillable());
            choiceProp.setIsRequired(next.isRequired());
            // handle XmlPath - if xml-path is set, we ignore name/namespace
            if (paths != null && next.getXmlPath() == null) {
                // Only set the path, if the path hasn't already been set from
                // xml
                XmlPath nextPath = paths[i];
                next.setXmlPath(nextPath.value());
            }
            if (next.getXmlPath() != null) {
                choiceProp.setXmlPath(next.getXmlPath());
                boolean isAttribute = new XMLField(next.getXmlPath()).getLastXPathFragment().isAttribute();
                // validate attribute - must be in nested path, not at root
                if (isAttribute && !next.getXmlPath().contains(SLASH)) {
                    throw JAXBException.invalidXmlPathWithAttribute(propertyName, cls.getQualifiedName(), next.getXmlPath());
                }
                choiceProp.setIsAttribute(isAttribute);
                name = XMLProcessor.getNameFromXPath(next.getXmlPath(), propertyName, isAttribute);
                namespace = XMLProcessor.DEFAULT;
            } else {
                // no xml-path, so use name/namespace from xml-element
                name = next.getName();
                namespace = next.getNamespace();
            }

            if (name == null || name.equals(XMLProcessor.DEFAULT)) {
                if (next.getJavaAttribute() != null) {
                    name = next.getJavaAttribute();
                } else {
                    name = propertyName;
                }
            }

            // if the property has xml-idref, the target type of each
            // xml-element in the list must have an xml-id property
            if (choiceProperty.isXmlIdRef()) {

                JavaClass nextCls =  helper.getJavaClass(next.getType());
                processReferencedClass(nextCls);
                TypeInfo tInfo = typeInfos.get(next.getType());


                if (tInfo == null || (!tInfo.isIDSet() && !preCheckXmlID(nextCls, tInfo))) {
                    throw JAXBException.invalidXmlElementInXmlElementsList(propertyName, name);
                }
            }

            QName qName = null;
            if (!namespace.equals(XMLProcessor.DEFAULT)) {
                qName = new QName(namespace, name);
            } else {
                NamespaceInfo namespaceInfo = getPackageInfoForPackage(cls).getNamespaceInfo();
                if (namespaceInfo.isElementFormQualified()) {
                    qName = new QName(namespaceInfo.getNamespace(), name);
                } else {
                    qName = new QName(name);
                }
            }

            choiceProp.setPropertyName(name);
            // figure out the property's type - note that for DEFAULT, if from
            // XML the value will
            // be "XmlElement.DEFAULT", and from annotations the value will be
            // "XmlElement$DEFAULT"
            if (next.getType().equals("jakarta.xml.bind.annotation.XmlElement.DEFAULT") || next.getType().equals("jakarta.xml.bind.annotation.XmlElement$DEFAULT")) {
                choiceProp.setType(propertyType);
            } else {
                choiceProp.setType(helper.getJavaClass(next.getType()));
            }
            // handle case of XmlJoinNodes w/XmlElements
            if (choiceProperty.isSetXmlJoinNodesList()) {
                // assumes one corresponding xml-join-nodes entry per
                // xml-element
                org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes xmlJoinNodes = choiceProperty.getXmlJoinNodesList().get(i);
                if (xmlJoinNodes != null) {
                    choiceProp.setXmlJoinNodes(xmlJoinNodes);
                    // set type
                    if (!xmlJoinNodes.getType().equals(XMLProcessor.DEFAULT)) {
                        JavaClass pType = helper.getJavaClass(xmlJoinNodes.getType());
                        if (helper.isCollectionType(choiceProp.getType())) {
                            choiceProp.setGenericType(pType);
                        } else {
                            choiceProp.setType(pType);
                        }
                    }
                }
            }

            choiceProp.setSchemaName(qName);
            choiceProp.setSchemaType(getSchemaTypeFor(choiceProp.getType()));
            choiceProp.setIsXmlIdRef(choiceProperty.isXmlIdRef());
            choiceProp.setXmlElementWrapper(choiceProperty.getXmlElementWrapper());
            choiceProperties.add(choiceProp);
            processReferencedClass(choiceProp.getType());
            TypeInfo newInfo = typeInfos.get(choiceProp.getType().getQualifiedName());
            if (newInfo != null && newInfo.isTransient()) {
                throw JAXBException.invalidReferenceToTransientClass(info.getJavaClassName(), choiceProperty.getPropertyName(), newInfo.getJavaClassName());
            }
        }
        choiceProperty.setChoiceProperties(choiceProperties);
    }

    /**
     * Check if class with specified non complete type info has @XmlID field.
     * Can update type info. Used in case when annotation processor analyze
     * inheritance (parent classes) and from parent class is reverse reference
     * via @XmlIDREF, @XmlPaths and @XmlElements to the some child classes.
     * In this phase type info is not complete (missing properties).
     */
    private boolean preCheckXmlID(JavaClass javaClass, TypeInfo typeInfo) {
        ArrayList<Property> properties = getPropertiesForClass(javaClass, typeInfo);
        for (Property property : properties) {
            // check @XmlID
            if (helper.isAnnotationPresent(property.getElement(), XmlID.class)) {
                return true;
            }
        }
        if (typeInfos.get(javaClass.getSuperclass().getQualifiedName()).isIDSet()) {
            if (typeInfo.getIDProperty() == null) {
                typeInfo.setIDProperty(typeInfos.get(javaClass.getSuperclass().getQualifiedName()).getIDProperty());
            }
            return true;
        }
        return false;
    }

    /**
     * Build a reference property. Here we will build a list of XML model
     * XmlElementRef objects, based on the @XmlElement(s) annotation, to store
     * on the Property. Processing of the elements and validation will be
     * performed during the finalize property phase via the
     * processReferenceProperty method.
     *
     */
    private Property buildReferenceProperty(TypeInfo info, JavaHasAnnotations javaHasAnnotations, String propertyName, JavaClass ptype) {
        Property property = new Property(helper);
        property.setType(ptype);

        XmlElementRef[] elementRefs;
        XmlElementRef ref = (XmlElementRef) helper.getAnnotation(javaHasAnnotations, XmlElementRef.class);
        if (ref != null) {
            elementRefs = new XmlElementRef[] { ref };
        } else {
            XmlElementRefs refs = (XmlElementRefs) helper.getAnnotation(javaHasAnnotations, XmlElementRefs.class);
            elementRefs = refs.value();
            info.setElementRefsPropertyName(propertyName);
        }

        List<org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef> eltRefs = new ArrayList<org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef>();
        for (XmlElementRef nextRef : elementRefs) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef eltRef = new org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef();
            eltRef.setName(nextRef.name());
            eltRef.setNamespace(nextRef.namespace());
            eltRef.setType(nextRef.type().getName());
            property.setIsRequired(true);
            try{
                Method requireMethod = PrivilegedAccessHelper.getMethod(XmlElementRef.class, "required", new Class[0], true);
                if(requireMethod != null){
                    Boolean val = PrivilegedAccessHelper.invokeMethod(requireMethod, nextRef);
                    property.setIsRequired(val);
                }
            } catch (Exception exception){
            }
            eltRefs.add(eltRef);
        }

        property.setIsReference(true);
        property.setXmlElementRefs(eltRefs);
        return property;
    }

    /**
     * Build a reference property.
     *
     */
    private Property processReferenceProperty(Property property, TypeInfo info, JavaClass cls) {

        for (org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef nextRef : property.getXmlElementRefs()) {
            JavaClass type = property.getType();
            String typeName;
            if (helper.isCollectionType(property.getType())) {
                if (type.hasActualTypeArguments()) {
                    type = property.getGenericType();
                    typeName = type.getQualifiedName();
                }
            }

            if (!(nextRef.getType().equals("jakarta.xml.bind.annotation.XmlElementRef.DEFAULT") || nextRef.getType().equals("jakarta.xml.bind.annotation.XmlElementRef$DEFAULT"))) {
                typeName = nextRef.getType();
                type = helper.getJavaClass(typeName);
            }

            boolean missingReference = true;
            for (Entry<String, ElementDeclaration> entry : xmlRootElements.entrySet()) {
                ElementDeclaration entryValue = entry.getValue();
                if (!(areEquals(type, Object.class)) && type.isAssignableFrom(entryValue.getJavaType())) {
                    addReferencedElement(property, entryValue);
                    missingReference = false;
                }
            }
            if (missingReference) {
                String name = nextRef.getName();
                String namespace = nextRef.getNamespace();
                if (namespace.equals(XMLProcessor.DEFAULT)) {
                    namespace = EMPTY_STRING;
                }
                QName qname = new QName(namespace, name);
                JavaClass scopeClass = cls;
                ElementDeclaration referencedElement = null;
                while (!(scopeClass.getName().equals(JAVA_LANG_OBJECT))) {
                    Map<QName, ElementDeclaration> elements = getElementDeclarationsForScope(scopeClass.getName());
                    if (elements != null) {
                        referencedElement = elements.get(qname);
                    }
                    if (referencedElement != null) {
                        break;
                    }
                    scopeClass = scopeClass.getSuperclass();
                }
                if (referencedElement == null) {
                    referencedElement = this.getGlobalElements().get(qname);
                }
                if (referencedElement != null) {
                    addReferencedElement(property, referencedElement);
                } else {
                    throw org.eclipse.persistence.exceptions.JAXBException.invalidElementRef(property.getPropertyName(), cls.getName());
                }
            }
        }
        return property;
    }

    private void processReferencePropertyTypes(Property property, TypeInfo info, JavaClass theClass) {
        for (org.eclipse.persistence.jaxb.xmlmodel.XmlElementRef nextRef : property.getXmlElementRefs()) {
            JavaClass type = property.getType();
            String typeName = type.getQualifiedName();
            if (helper.isCollectionType(property.getType())) {
                if (type.hasActualTypeArguments()) {
                    type = property.getGenericType();
                    typeName = type.getQualifiedName();
                }
            }

            if(JAVAX_XML_BIND_JAXBELEMENT.equals(typeName)){
                Collection args = type.getActualTypeArguments();
                if(args.size() > 0){
                    JavaClass theType = (JavaClass) args.iterator().next();
                    processReferencedClass(theType);
                }
            }

            // for DEFAULT, if from XML the type will be
            // "XmlElementRef.DEFAULT",
            // and from annotations the value will be "XmlElementref$DEFAULT"
            if (!(nextRef.getType().equals("jakarta.xml.bind.annotation.XmlElementRef.DEFAULT") || nextRef.getType().equals("jakarta.xml.bind.annotation.XmlElementRef$DEFAULT"))) {
                typeName = nextRef.getType();
                type = helper.getJavaClass(typeName);
            }
            processReferencedClass(type);
        }
    }

    private void processPropertyAnnotations(TypeInfo info, JavaClass cls, JavaHasAnnotations propertyElement, Property property) {
        // Check for mixed context
        if (helper.isAnnotationPresent(propertyElement, XmlMixed.class)) {
            info.setMixed(true);
            property.setMixedContent(true);
            findAndProcessObjectFactory(cls);
        }
        if (helper.isAnnotationPresent(propertyElement, XmlInverseReference.class)) {
            XmlInverseReference inverseReference = (XmlInverseReference) helper.getAnnotation(propertyElement, XmlInverseReference.class);
            property.setInverseReferencePropertyName(inverseReference.mappedBy());

            TypeInfo targetInfo = this.getTypeInfos().get(property.getActualType().getName());
            if (targetInfo != null && targetInfo.getXmlAccessType() == XmlAccessType.PROPERTY) {
                String propName = property.getPropertyName();
                propName = Character.toUpperCase(propName.charAt(0)) + propName.substring(1);
                property.setInverseReferencePropertyGetMethodName(GET_STR + propName);
                property.setInverseReferencePropertySetMethodName(SET_STR + propName);
            }

            property.setInverseReference(true, helper.isAnnotationPresent(propertyElement, XmlElement.class));
        }

        processXmlJavaTypeAdapter(property, info, cls);
        if (helper.isAnnotationPresent(propertyElement, XmlAttachmentRef.class) && areEquals(property.getActualType(), JAVAX_ACTIVATION_DATAHANDLER)) {
            property.setIsSwaAttachmentRef(true);
            property.setSchemaType(Constants.SWA_REF_QNAME);
        }
        processXmlElement(property, info);

        // JavaClass ptype = property.getActualType();
        if (!(property.isSwaAttachmentRef()) && isMtomAttachment(property)) {
            property.setIsMtomAttachment(true);
            property.setSchemaType(Constants.BASE_64_BINARY_QNAME);
        }
        if (helper.isAnnotationPresent(propertyElement, XmlMimeType.class)) {
            property.setMimeType(((XmlMimeType) helper.getAnnotation(propertyElement, XmlMimeType.class)).value());
        }
        // set indicator for inlining binary data - setting this to true on a
        // non-binary data type won't have any affect
        if (helper.isAnnotationPresent(propertyElement, XmlInlineBinaryData.class) || info.isBinaryDataToBeInlined()) {
            property.setisInlineBinaryData(true);
        }

        // Get schema-type info if specified and set it on the property for
        // later use:
        if (helper.isAnnotationPresent(propertyElement, XmlSchemaType.class)) {
            XmlSchemaType schemaType = (XmlSchemaType) helper.getAnnotation(propertyElement, XmlSchemaType.class);
            QName schemaTypeQname = new QName(schemaType.namespace(), schemaType.name());
            property.setSchemaType(schemaTypeQname);
        }

        if (helper.isAnnotationPresent(propertyElement, XmlAttribute.class)) {
            property.setIsAttribute(true);
            property.setIsRequired(((XmlAttribute) helper.getAnnotation(propertyElement, XmlAttribute.class)).required());
        }

        if (helper.isAnnotationPresent(propertyElement, XmlAnyAttribute.class)) {
            if (info.isSetAnyAttributePropertyName() && !info.getAnyAttributePropertyName().equals(property.getPropertyName())) {
                throw org.eclipse.persistence.exceptions.JAXBException.multipleAnyAttributeMapping(cls.getName());
            }
            if (!helper.isMapType(property.getType())) {
                throw org.eclipse.persistence.exceptions.JAXBException.anyAttributeOnNonMap(property.getPropertyName());
            }
            property.setIsAnyAttribute(true);
            info.setAnyAttributePropertyName(property.getPropertyName());
        }

        // Make sure XmlElementWrapper annotation is on a collection or array
        if (helper.isAnnotationPresent(propertyElement, XmlElementWrapper.class)) {
            XmlElementWrapper wrapper = (XmlElementWrapper) helper.getAnnotation(propertyElement, XmlElementWrapper.class);
            org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper xmlEltWrapper = new org.eclipse.persistence.jaxb.xmlmodel.XmlElementWrapper();

            String wrapperName = wrapper.name();
            if (wrapperName.equals(XMLProcessor.DEFAULT)) {
                wrapperName = info.getXmlNameTransformer().transformElementName(property.getPropertyName());
            }
            xmlEltWrapper.setName(wrapperName);
            xmlEltWrapper.setNamespace(wrapper.namespace());
            xmlEltWrapper.setNillable(wrapper.nillable());
            xmlEltWrapper.setRequired(wrapper.required());
            property.setXmlElementWrapper(xmlEltWrapper);
        }

        if (helper.isAnnotationPresent(propertyElement, XmlList.class)) {
            // Make sure XmlList annotation is on a collection or array
            if (!helper.isCollectionType(property.getType()) && !property.getType().isArray()) {
                throw JAXBException.invalidList(property.getPropertyName());
            }
            property.setIsXmlList(true);
        }

        if (helper.isAnnotationPresent(propertyElement, XmlValue.class)) {
            property.setIsXmlValue(true);
            info.setXmlValueProperty(property);
        }

        if (helper.isAnnotationPresent(propertyElement, XmlReadOnly.class)) {
            property.setReadOnly(true);
        }
        if (helper.isAnnotationPresent(propertyElement, XmlWriteOnly.class)) {
            property.setWriteOnly(true);
        }
        if (helper.isAnnotationPresent(propertyElement, XmlCDATA.class)) {
            property.setCdata(true);
        }
        if (helper.isAnnotationPresent(propertyElement, XmlAccessMethods.class)) {
            XmlAccessMethods accessMethods = (XmlAccessMethods) helper.getAnnotation(propertyElement, XmlAccessMethods.class);
            if (!(accessMethods.getMethodName().equals(EMPTY_STRING))) {
                property.setGetMethodName(accessMethods.getMethodName());
            }
            if (!(accessMethods.setMethodName().equals(EMPTY_STRING))) {
                property.setSetMethodName(accessMethods.setMethodName());
            }
            if (!(property.isMethodProperty())) {
                property.setMethodProperty(true);
            }
        }

        // handle user properties
        if (helper.isAnnotationPresent(propertyElement, XmlProperties.class)) {
            XmlProperties xmlProperties = (XmlProperties) helper.getAnnotation(propertyElement, XmlProperties.class);
            Map<Object, Object> propertiesMap = createUserPropertiesMap(xmlProperties.value());
            property.setUserProperties(propertiesMap);
        } else if (helper.isAnnotationPresent(propertyElement, XmlProperty.class)) {
            XmlProperty xmlProperty = (XmlProperty) helper.getAnnotation(propertyElement, XmlProperty.class);
            Map<Object, Object> propertiesMap = createUserPropertiesMap(new XmlProperty[] { xmlProperty });
            property.setUserProperties(propertiesMap);
        }
        // handle XmlKey
        if (helper.isAnnotationPresent(propertyElement, XmlKey.class)) {
            info.addXmlKeyProperty(property);
        }
        // handle XmlJoinNode(s)
        processXmlJoinNodes(property);
        processXmlNullPolicy(property, cls, info);

        // Handle XmlLocation
        JavaHasAnnotations elem = propertyElement;
        if (helper.isAnnotationPresent(elem, XmlLocation.class)
                || helper.isAnnotationPresent(elem, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS)
                || helper.isAnnotationPresent(elem, CompilerHelper.OLD_XML_LOCATION_ANNOTATION_CLASS)
                || helper.isAnnotationPresent(elem, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS)) {
            if (!helper.getJavaClass(Constants.LOCATOR_CLASS).isAssignableFrom(property.getType())) {
                throw JAXBException.invalidXmlLocation(property.getPropertyName(), property.getType().getName());
            }
            property.setXmlLocation(true);
        }
    }

    /**
     * Process XmlJoinNode(s) for a given Property. An
     * org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNode(s) will be
     * created/populated using the annotation, and set on the Property for later
     * processing.
     *
     * It is assumed that for a single join node XmlJoinNode will be used, and
     * for multiple join nodes XmlJoinNodes will be used.
     *
     * @param property
     * Property that may contain @XmlJoinNodes/@XmlJoinNode
     */
    private void processXmlJoinNodes(Property property) {
        List<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode> xmlJoinNodeList;
        org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode xmlJoinNode;
        org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes xmlJoinNodes;
        // handle XmlJoinNodes
        if (helper.isAnnotationPresent(property.getElement(), XmlJoinNodes.class)) {
            xmlJoinNodeList = new ArrayList<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode>();
            for (XmlJoinNode xmlJN : ((XmlJoinNodes) helper.getAnnotation(property.getElement(), XmlJoinNodes.class)).value()) {
                xmlJoinNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode();
                xmlJoinNode.setXmlPath(xmlJN.xmlPath());
                xmlJoinNode.setReferencedXmlPath(xmlJN.referencedXmlPath());
                xmlJoinNodeList.add(xmlJoinNode);
            }
            xmlJoinNodes = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes();
            xmlJoinNodes.setXmlJoinNode(xmlJoinNodeList);
            property.setXmlJoinNodes(xmlJoinNodes);
        }
        // handle XmlJoinNode
        else if (helper.isAnnotationPresent(property.getElement(), XmlJoinNode.class)) {
            XmlJoinNode xmlJN = (XmlJoinNode) helper.getAnnotation(property.getElement(), XmlJoinNode.class);
            xmlJoinNode = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode();
            xmlJoinNode.setXmlPath(xmlJN.xmlPath());
            xmlJoinNode.setReferencedXmlPath(xmlJN.referencedXmlPath());
            xmlJoinNodeList = new ArrayList<org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes.XmlJoinNode>();
            xmlJoinNodeList.add(xmlJoinNode);
            xmlJoinNodes = new org.eclipse.persistence.jaxb.xmlmodel.XmlJoinNodes();
            xmlJoinNodes.setXmlJoinNode(xmlJoinNodeList);
            property.setXmlJoinNodes(xmlJoinNodes);
        }
    }

    /**
     * Responsible for validating transformer settings on a given property.
     * Validates that for field transformers either a transformer class OR
     * method name is set (not both) and that an xml-path is set. Validates that
     * for attribute transformers either a transformer class OR method name is
     * set (not both).
     *
     */
    private void validateXmlTransformationProperty(Property property) {
        if (property.isSetXmlTransformation()) {
            XmlTransformation xmlTransformation = property.getXmlTransformation();
            // validate transformer(s)
            if (xmlTransformation.isSetXmlReadTransformer()) {
                // validate read transformer
                XmlReadTransformer readTransformer = xmlTransformation.getXmlReadTransformer();
                if (readTransformer.isSetTransformerClass()) {
                    // handle read transformer class
                    if (readTransformer.isSetMethod()) {
                        // cannot have both class and method set
                        throw JAXBException.readTransformerHasBothClassAndMethod(property.getPropertyName());
                    }
                } else {
                    // handle read transformer method
                    if (!readTransformer.isSetMethod()) {
                        // require class or method to be set
                        throw JAXBException.readTransformerHasNeitherClassNorMethod(property.getPropertyName());
                    }
                }
            }
            if (xmlTransformation.isSetXmlWriteTransformers()) {
                // handle write transformer(s)
                for (XmlWriteTransformer writeTransformer : xmlTransformation.getXmlWriteTransformer()) {
                    // must have an xml-path set
                    if (!writeTransformer.isSetXmlPath()) {
                        throw JAXBException.writeTransformerHasNoXmlPath(property.getPropertyName());
                    }
                    if (writeTransformer.isSetTransformerClass()) {
                        // handle write transformer class
                        if (writeTransformer.isSetMethod()) {
                            // cannot have both class and method set
                            throw JAXBException.writeTransformerHasBothClassAndMethod(property.getPropertyName(), writeTransformer.getXmlPath());
                        }
                    } else {
                        // handle write transformer method
                        if (!writeTransformer.isSetMethod()) {
                            // require class or method to be set
                            throw JAXBException.writeTransformerHasNeitherClassNorMethod(property.getPropertyName(), writeTransformer.getXmlPath());
                        }
                    }
                }
            }
        }
    }

    /**
     * Compares a JavaModel JavaClass to a Class. Equality is based on the raw
     * name of the JavaClass compared to the canonical name of the Class.
     *
     */
    protected boolean areEquals(JavaClass src, Class tgt) {
        if (src == null || tgt == null) {
            return false;
        }
        return src.getRawName().equals(tgt.getCanonicalName());
    }

    private void processXmlNullPolicy(Property property, JavaClass cls, TypeInfo info) {
        if (propertyHasXmlNullPolicyAnnotation(property)) {
            setNullPolicyOnProperty(property, helper.getAnnotation(property.getElement(), XmlNullPolicy.class));
        } else if (existsExternalMappingWithJavaTypeXmlNullPolicy(info)) {
            property.setNullPolicy(info.getXmlNullPolicy());
        } else if (javaTypeHasXmlNullPolicyAnnotation(cls)) {
            setNullPolicyOnProperty(property, helper.getAnnotation(cls, XmlNullPolicy.class));
        } else if (existsExternaMappingWithPackageXmlNullPolicy(cls)) {
            property.setNullPolicy(packageToXmlNillableInfoMappings.get(cls.getPackageName()).getXmlNullPolicy());
        } else if (helper.isAnnotationPresent(cls.getPackage(), XmlNullPolicy.class)) {
            setNullPolicyOnProperty(property, helper.getAnnotation(cls.getPackage(), XmlNullPolicy.class));
        } else if (helper.isAnnotationPresent(property.getElement(), XmlIsSetNullPolicy.class)) {
            XmlIsSetNullPolicy nullPolicy = (XmlIsSetNullPolicy) helper.getAnnotation(property.getElement(), XmlIsSetNullPolicy.class);
            org.eclipse.persistence.jaxb.xmlmodel.XmlIsSetNullPolicy policy = new org.eclipse.persistence.jaxb.xmlmodel.XmlIsSetNullPolicy();
            policy.setEmptyNodeRepresentsNull(nullPolicy.emptyNodeRepresentsNull());
            policy.setXsiNilRepresentsNull(nullPolicy.xsiNilRepresentsNull());
            policy.setNullRepresentationForXml(org.eclipse.persistence.jaxb.xmlmodel.XmlMarshalNullRepresentation.valueOf(nullPolicy.nullRepresentationForXml().toString()));
            policy.setIsSetMethodName(nullPolicy.isSetMethodName());
            for (XmlParameter next : nullPolicy.isSetParameters()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlIsSetNullPolicy.IsSetParameter param = new org.eclipse.persistence.jaxb.xmlmodel.XmlIsSetNullPolicy.IsSetParameter();
                param.setValue(next.value());
                param.setType(next.type().getName());
                policy.getIsSetParameter().add(param);
            }
            property.setNullPolicy(policy);
        }
    }

    private boolean existsExternaMappingWithPackageXmlNullPolicy(JavaClass cls) {

        if (null == packageToXmlNillableInfoMappings || !packageToXmlNillableInfoMappings.containsKey(cls.getPackageName())) {
            return false;
        }

        return null != packageToXmlNillableInfoMappings.get(cls.getPackageName()).getXmlNullPolicy();
    }

    private boolean javaTypeHasXmlNullPolicyAnnotation(JavaClass cls) {
        return helper.isAnnotationPresent(cls, XmlNullPolicy.class);
    }

    private boolean existsExternalMappingWithJavaTypeXmlNullPolicy(TypeInfo info) {
        return null != info.getXmlNullPolicy();
    }

    private boolean propertyHasXmlNullPolicyAnnotation(Property property) {
        return helper.isAnnotationPresent(property.getElement(), XmlNullPolicy.class);
    }

    private void setNullPolicyOnProperty(Property property, Annotation nullPolicyAnnotation) {
        XmlNullPolicy nullPolicy = (XmlNullPolicy) nullPolicyAnnotation;
        org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy policy = new org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy();
        policy.setEmptyNodeRepresentsNull(nullPolicy.emptyNodeRepresentsNull());
        policy.setIsSetPerformedForAbsentNode(nullPolicy.isSetPerformedForAbsentNode());
        policy.setXsiNilRepresentsNull(nullPolicy.xsiNilRepresentsNull());
        policy.setNullRepresentationForXml(org.eclipse.persistence.jaxb.xmlmodel.XmlMarshalNullRepresentation.valueOf(nullPolicy.nullRepresentationForXml().toString()));
        property.setNullPolicy(policy);
    }

    /**
     * Compares a JavaModel JavaClass to a Class. Equality is based on the raw
     * name of the JavaClass compared to the canonical name of the Class.
     *
     */
    protected boolean areEquals(JavaClass src, String tgtCanonicalName) {
        if (src == null || tgtCanonicalName == null) {
            return false;
        }
        return src.getRawName().equals(tgtCanonicalName);
    }

    public ArrayList<Property> getPropertyPropertiesForClass(JavaClass cls, TypeInfo info, boolean onlyPublic) {
        return getPropertyPropertiesForClass(cls, info, onlyPublic, false);
    }

    public ArrayList<Property> getPropertyPropertiesForClass(JavaClass cls, TypeInfo info, boolean onlyPublic, boolean onlyExplicit) {
        ArrayList<Property> properties = new ArrayList<Property>();
        if (cls == null) {
            return properties;
        }

        // First collect all the getters and setters
        ArrayList<JavaMethod> propertyMethods = new ArrayList<JavaMethod>();
        for (JavaMethod next : new ArrayList<JavaMethod>(cls.getDeclaredMethods())) {
            if(!next.isSynthetic()){
                if (((next.getName().startsWith(GET_STR) && next.getName().length() > 3) || (next.getName().startsWith(IS_STR) && next.getName().length() > 2)) && next.getParameterTypes().length == 0 && next.getReturnType() != helper.getJavaClass(java.lang.Void.class)) {
                    int modifiers = next.getModifiers();

                    if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers) && ((onlyPublic && Modifier.isPublic(next.getModifiers())) || !onlyPublic || hasJAXBAnnotations(next))) {
                        propertyMethods.add(next);
                    }
                } else if (next.getName().startsWith(SET_STR) && next.getName().length() > 3 && next.getParameterTypes().length == 1) {
                    int modifiers = next.getModifiers();
                    if (!Modifier.isStatic(modifiers) && !Modifier.isTransient(modifiers) && ((onlyPublic && Modifier.isPublic(next.getModifiers())) || !onlyPublic || hasJAXBAnnotations(next))) {
                        propertyMethods.add(next);
                    }
                }
            }
        }
        // Next iterate over the getters and find their setter methods, add
        // whichever one is
        // annotated to the properties list. If neither is, use the getter

        // keep track of property names to avoid processing the same property
        // twice (for getter and setter)
        List<String> propertyNames = new ArrayList<String>();
        for (JavaMethod propertyMethod1 : propertyMethods) {
            boolean isPropertyTransient = false;
            JavaMethod nextMethod = propertyMethod1;
            String propertyName = EMPTY_STRING;

            JavaMethod getMethod;
            JavaMethod setMethod;

            JavaMethod propertyMethod = null;

            if (!nextMethod.getName().startsWith(SET_STR)) {
                if (nextMethod.getName().startsWith(GET_STR)) {
                    propertyName = nextMethod.getName().substring(3);
                } else if (nextMethod.getName().startsWith(IS_STR)) {
                    propertyName = nextMethod.getName().substring(2);
                }
                getMethod = nextMethod;
                String setMethodName = SET_STR + propertyName;

                // use the JavaBean API to correctly decapitalize the first
                // character, if necessary
                propertyName = Introspector.decapitalize(propertyName);

                JavaClass[] paramTypes = { getMethod.getReturnType() };
                setMethod = cls.getDeclaredMethod(setMethodName, paramTypes);

                if (setMethod == null) {
                    //if there's no locally declared set method, check for an inherited
                    //set method
                    setMethod = cls.getMethod(setMethodName, paramTypes);
                }
                if (setMethod == null && !(hasJAXBAnnotations(getMethod))) {
                    //if there's no corresponding setter, and not explicitly
                    //annotated, don't process
                    isPropertyTransient = true;
                }

                if (setMethod != null && hasJAXBAnnotations(setMethod)) {
                    // use the set method if it exists and is annotated
                    boolean isTransient = helper.isAnnotationPresent(setMethod, XmlTransient.class);
                    boolean isLocation = helper.isAnnotationPresent(setMethod, XmlLocation.class) ||
                            helper.isAnnotationPresent(setMethod, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS) ||
                            helper.isAnnotationPresent(setMethod, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS);
                    propertyMethod = setMethod;
                    if (isTransient) {
                        isPropertyTransient = true;
                        // XmlLocation can also be transient
                        if (isLocation) {
                            info.setLocationAware(true);
                        }
                    }
                } else if ((onlyExplicit && hasJAXBAnnotations(getMethod)) || !onlyExplicit) {
                    boolean isTransient = helper.isAnnotationPresent(getMethod, XmlTransient.class);
                    boolean isLocation = helper.isAnnotationPresent(getMethod, XmlLocation.class) ||
                            helper.isAnnotationPresent(setMethod, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS) ||
                            helper.isAnnotationPresent(setMethod, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS);
                    propertyMethod = getMethod;
                    if (isTransient) {
                        isPropertyTransient = true;
                        // XmlLocation can also be transient
                        if (isLocation) {
                            info.setLocationAware(true);
                        }
                    }
                } else if (onlyExplicit) {
                    continue;
                }
            } else {
                propertyName = nextMethod.getName().substring(3);
                setMethod = nextMethod;

                String getMethodName = GET_STR + propertyName;

                getMethod = cls.getDeclaredMethod(getMethodName, new JavaClass[] { });
                if (getMethod == null) {
                    // try is instead of get
                    getMethodName = IS_STR + propertyName;
                    getMethod = cls.getDeclaredMethod(getMethodName, new JavaClass[] { });
                }

                //may look for get method on parent class
                if (getMethod == null) {
                    //look for inherited getMethod
                    getMethod = cls.getMethod(GET_STR + propertyName, new JavaClass[] { });
                    if (getMethod == null) {
                        getMethod = cls.getMethod(IS_STR + propertyName, new JavaClass[] { });
                    }
                }
                if (getMethod == null && !(hasJAXBAnnotations(setMethod))) {
                    isPropertyTransient = true;
                }
                if (getMethod != null && hasJAXBAnnotations(getMethod)) {
                    // use the get method if it exists and is annotated
                    boolean isTransient = helper.isAnnotationPresent(getMethod, XmlTransient.class);
                    boolean isLocation = helper.isAnnotationPresent(getMethod, XmlLocation.class) ||
                            helper.isAnnotationPresent(getMethod, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS) ||
                            helper.isAnnotationPresent(getMethod, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS);
                    propertyMethod = getMethod;
                    if (isTransient) {
                        isPropertyTransient = true;
                        // XmlLocation can also be transient
                        if (isLocation) {
                            info.setLocationAware(true);
                        }
                    }
                } else if ((onlyExplicit && hasJAXBAnnotations(setMethod)) || !onlyExplicit) {
                    boolean isTransient = helper.isAnnotationPresent(setMethod, XmlTransient.class);
                    boolean isLocation = helper.isAnnotationPresent(setMethod, XmlLocation.class) ||
                            helper.isAnnotationPresent(getMethod, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS) ||
                            helper.isAnnotationPresent(getMethod, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS);
                    propertyMethod = setMethod;
                    if (isTransient) {
                        isPropertyTransient = true;
                        // XmlLocation can also be transient
                        if (isLocation) {
                            info.setLocationAware(true);
                        }
                    }
                } else if (onlyExplicit) {
                    continue;
                }
                // use the JavaBean API to correctly decapitalize the first
                // character, if necessary
                propertyName = Introspector.decapitalize(propertyName);
            }

            JavaClass ptype = null;
            if (getMethod != null) {
                ptype = getMethod.getReturnType();
            } else {
                ptype = setMethod.getParameterTypes()[0];
            }

            if (!propertyNames.contains(propertyName)) {
                try {
                    Property property = buildNewProperty(info, cls, propertyMethod, propertyName, ptype);
                    propertyNames.add(propertyName);
                    property.setTransient(isPropertyTransient);

                    if (getMethod != null) {
                        property.setOriginalGetMethodName(getMethod.getName());
                        if (property.getGetMethodName() == null) {
                            property.setGetMethodName(getMethod.getName());
                        }
                    }
                    if (setMethod != null) {
                        property.setOriginalSetMethodName(setMethod.getName());
                        if (property.getSetMethodName() == null) {
                            property.setSetMethodName(setMethod.getName());
                        }
                    }
                    property.setMethodProperty(true);

                    //boolean isTransient = helper.isAnnotationPresent(property.getElement(), XmlTransient.class);
                    //boolean isLocation = helper.isAnnotationPresent(property.getElement(), XmlLocation.class) ||
                    //        helper.isAnnotationPresent(setMethod, CompilerHelper.XML_LOCATION_ANNOTATION_CLASS) ||
                    //        helper.isAnnotationPresent(setMethod, CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_CLASS);
                    //if (!isTransient || (isTransient && isLocation)) {
                    properties.add(property);
                    //}
                } catch (JAXBException ex) {
                    if (ex.getErrorCode() != JAXBException.INVALID_INTERFACE || !isPropertyTransient) {
                        throw ex;
                    }
                }
            }
        }

        properties = removeSuperclassProperties(cls, properties);

        // default to alphabetical ordering
        // RI compliancy
        Collections.sort(properties, new PropertyComparitor());
        return properties;
    }

    private ArrayList<Property> removeSuperclassProperties(JavaClass cls, ArrayList<Property> properties) {
        ArrayList<Property> revisedProperties = new ArrayList<Property>();
        revisedProperties.addAll(properties);

        // Check for any get() methods that are overridden in the subclass.
        // If we find any, remove the property, because it is already defined on
        // the superclass.
        JavaClass superClass = cls.getSuperclass();
        if (null != superClass) {
            TypeInfo superClassInfo = typeInfos.get(superClass.getQualifiedName());
            if (superClassInfo != null && !superClassInfo.isTransient()) {
                for (Property prop : properties) {
                    for (Property superProp : superClassInfo.getProperties().values()) {
                        if (superProp.getGetMethodName() != null && superProp.getGetMethodName().equals(prop.getGetMethodName()) && !superProp.isTransient()) {
                            revisedProperties.remove(prop);
                        }
                    }
                }
            }
        }

        return revisedProperties;
    }

    public ArrayList getPublicMemberPropertiesForClass(JavaClass cls, TypeInfo info) {
        ArrayList<Property> fieldProperties = getFieldPropertiesForClass(cls, info, !hasXmlBindings());
        ArrayList<Property> methodProperties = getPropertyPropertiesForClass(cls, info, !hasXmlBindings());

        // filter out non-public properties that aren't annotated
        ArrayList<Property> publicFieldProperties = new ArrayList<Property>();
        ArrayList<Property> publicMethodProperties = new ArrayList<Property>();

        for (Property next : fieldProperties) {
            if (Modifier.isPublic(((JavaField) next.getElement()).getModifiers())) {
                publicFieldProperties.add(next);
            } else {
                if (hasJAXBAnnotations(next.getElement())) {
                    publicFieldProperties.add(next);
                }
            }
        }

        for (Property next : methodProperties) {
            if (next.getElement() != null) {
                if (Modifier.isPublic(((JavaMethod) next.getElement()).getModifiers())) {
                    publicMethodProperties.add(next);
                } else {
                    if (hasJAXBAnnotations(next.getElement())) {
                        publicMethodProperties.add(next);
                    }
                }
            }
        }

        // Not sure who should win if a property exists for both or the correct
        // order
        if (publicFieldProperties.size() >= 0 && publicMethodProperties.size() == 0) {
            return publicFieldProperties;
        } else if (publicMethodProperties.size() > 0 && publicFieldProperties.size() == 0) {
            return publicMethodProperties;
        } else {
            // add any non-duplicate method properties to the collection.
            // - in the case of a collision if one is annotated use it,
            // otherwise
            // use the field.
            HashMap<String, Property> fieldPropertyMap = getPropertyMapFromArrayList(publicFieldProperties);
            for (Property publicMethodProperty : publicMethodProperties) {
                Property next = publicMethodProperty;
                Property fieldProp = fieldPropertyMap.get(next.getPropertyName());
                if (fieldProp == null) {
                    publicFieldProperties.add(next);
                } else if (fieldProp.isTransient()) {
                    //bug 346461 - if a public field is transient and the public methods are not
                    // then use the method
                    publicFieldProperties.remove(fieldProp);
                    publicFieldProperties.add(next);
                }
            }
            return publicFieldProperties;
        }
    }

    public HashMap<String, Property> getPropertyMapFromArrayList(ArrayList<Property> props) {
        HashMap propMap = new HashMap(props.size());

        for (Object next : props) {
            propMap.put(((Property)next).getPropertyName(), next);
        }
        return propMap;
    }

    public ArrayList getNoAccessTypePropertiesForClass(JavaClass cls, TypeInfo info) {
        ArrayList<Property> list = new ArrayList<Property>();
        if (cls == null) {
            return list;
        }

        // Iterate over the field and method properties. If ANYTHING contains an
        // annotation and
        // doesn't appear in the other list, add it to the final list
        List<Property> fieldProperties = getFieldPropertiesForClass(cls, info, false);
        Map<String, Property> fields = new HashMap<String, Property>(fieldProperties.size());
        for (Property next : fieldProperties) {
            JavaHasAnnotations elem = next.getElement();
            if (!hasJAXBAnnotations(elem)) {
                next.setTransient(true);
            }
            list.add(next);
            fields.put(next.getPropertyName(), next);
        }

        List<Property> methodProperties = getPropertyPropertiesForClass(cls, info, false);
        for (Property next : methodProperties) {
            JavaHasAnnotations elem = next.getElement();
            if (hasJAXBAnnotations(elem)) {
                // If the property is annotated remove the corresponding field
                Property fieldProperty = fields.get(next.getPropertyName());
                list.remove(fieldProperty);
                list.add(next);
            } else {
                // If the property is not annotated only add it if there is no
                // corresponding field.
                next.setTransient(true);
                if (fields.get(next.getPropertyName()) == null) {
                    list.add(next);
                }
            }
        }
        return list;
    }

    /**
     * Use name, namespace and type information to setup a user-defined schema
     * type. This method will typically be called when processing an
     *
     * {@literal @XmlSchemaType(s)} annotation or xml-schema-type(s) metadata.
     *
     */
    public void processSchemaType(String name, String namespace, String jClassQualifiedName) {
        this.userDefinedSchemaTypes.put(jClassQualifiedName, new QName(namespace, name));
    }

    public void processSchemaType(XmlSchemaType type) {
        JavaClass jClass = helper.getJavaClass(type.type());
        if (jClass == null) {
            return;
        }
        processSchemaType(type.name(), type.namespace(), jClass.getQualifiedName());
    }

    public void addEnumTypeInfo(JavaClass javaClass, EnumTypeInfo info) {
        if (javaClass == null) {
            return;
        }

        info.setClassName(javaClass.getQualifiedName());
        Class restrictionClass = String.class;
        QName restrictionBase = getSchemaTypeFor(helper.getJavaClass(restrictionClass));

        if (helper.isAnnotationPresent(javaClass, XmlEnum.class)) {
            XmlEnum xmlEnum = (XmlEnum) helper.getAnnotation(javaClass, XmlEnum.class);
            restrictionClass = xmlEnum.value();
            JavaClass restrictionJavaClass= helper.getJavaClass(restrictionClass);
            boolean restrictionIsEnum = helper.isAnnotationPresent(restrictionJavaClass, XmlEnum.class);

            if(!restrictionIsEnum){
                if(helper.isBuiltInJavaType(restrictionJavaClass)){
                    restrictionBase = getSchemaTypeFor(helper.getJavaClass(restrictionClass));
                }else{
                    TypeInfo restrictionInfo = typeInfos.get(restrictionJavaClass.getQualifiedName());
                    if(restrictionInfo == null){
                        JavaClass[] jClasses = new JavaClass[] { restrictionJavaClass };
                        buildNewTypeInfo(jClasses);
                        restrictionInfo = typeInfos.get(restrictionJavaClass.getQualifiedName());
                    }else if(!restrictionInfo.isPostBuilt()){
                        postBuildTypeInfo(new JavaClass[] { restrictionJavaClass });
                    }

                    Property xmlValueProp = restrictionInfo.getXmlValueProperty();
                    if(xmlValueProp != null){
                        restrictionJavaClass = xmlValueProp.getActualType();
                        restrictionBase = getSchemaTypeFor(restrictionJavaClass);
                        restrictionClass = helper.getClassForJavaClass(restrictionJavaClass);
                    }
                }
            }else{
                while (restrictionIsEnum) {

                    TypeInfo restrictionTypeInfo = processReferencedClass(restrictionJavaClass);
                    restrictionBase = new QName(restrictionTypeInfo.getClassNamespace(), restrictionTypeInfo.getSchemaTypeName());

                    xmlEnum = (XmlEnum) helper.getAnnotation(restrictionJavaClass, XmlEnum.class);
                    restrictionClass = xmlEnum.value();
                    restrictionJavaClass= helper.getJavaClass(restrictionClass);
                    restrictionIsEnum = helper.isAnnotationPresent(restrictionJavaClass, XmlEnum.class);
                }
            }
        }
        info.setRestrictionBase(restrictionBase);

        for (JavaField field : (Iterable<JavaField>) javaClass.getDeclaredFields()) {
            if (field.isEnumConstant()) {
                Object enumValue = field.getName();
                if (helper.isAnnotationPresent(field, XmlEnumValue.class)) {
                    enumValue = ((XmlEnumValue) helper.getAnnotation(field, XmlEnumValue.class)).value();
                }
                if (restrictionClass != null) {
                    try {
                        enumValue = XMLConversionManager.getDefaultXMLManager().convertObject(enumValue, restrictionClass);
                    } catch (ConversionException e) {
                        throw JAXBException.invalidEnumValue(enumValue, restrictionClass.getName(), e);
                    }

                }
                info.addJavaFieldToXmlEnumValuePair(field.getName(), enumValue);
            }
        }
        // Add a non-named element declaration for each enumeration to trigger
        // class generation
        if(info.getXmlRootElement() == null) {
            //process the root element and use that as the element
            ElementDeclaration elem = new ElementDeclaration(null, javaClass, javaClass.getQualifiedName(), false);
            this.getLocalElements().add(elem);
        }
    }

    public QName getSchemaTypeOrNullFor(JavaClass javaClass) {
        if (javaClass == null) {
            return null;
        }

        // check user defined types first
        QName schemaType = userDefinedSchemaTypes.get(javaClass.getQualifiedName());
        if (schemaType == null) {
            schemaType = (QName) helper.getXMLToJavaTypeMap().get(javaClass.getRawName());
        }
        return schemaType;
    }

    public QName getSchemaTypeFor(JavaClass javaClass) {
        QName schemaType = getSchemaTypeOrNullFor(javaClass);
        if (schemaType == null) {
            return Constants.ANY_SIMPLE_TYPE_QNAME;
        }
        return schemaType;
    }

    public NamespaceInfo processNamespaceInformation(XmlSchema xmlSchema) {
        NamespaceInfo info = new NamespaceInfo();
        info.setNamespaceResolver(new NamespaceResolver());
        String packageNamespace = null;
        if (xmlSchema != null) {
            String namespaceMapping = xmlSchema.namespace();
            if (!(namespaceMapping.equals(EMPTY_STRING) || namespaceMapping.equals(XMLProcessor.DEFAULT))) {
                packageNamespace = namespaceMapping;
            } else if (namespaceMapping.equals(XMLProcessor.DEFAULT)) {
                packageNamespace = this.defaultTargetNamespace;
            }
            info.setNamespace(packageNamespace);
            XmlNs[] xmlns = xmlSchema.xmlns();
            for (XmlNs next : xmlns) {
                info.getNamespaceResolver().put(next.prefix(), next.namespaceURI());
            }
            info.setAttributeFormQualified(xmlSchema.attributeFormDefault() == XmlNsForm.QUALIFIED);
            info.setElementFormQualified(xmlSchema.elementFormDefault() == XmlNsForm.QUALIFIED);

            // reflectively load XmlSchema class to avoid dependency
            try {
                Method locationMethod = PrivilegedAccessHelper.getDeclaredMethod(XmlSchema.class, "location", new Class[] {});
                String location = PrivilegedAccessHelper.invokeMethod(locationMethod, xmlSchema, new Object[] {});

                if (location != null) {
                    if (location.equals("##generate")) {
                        location = null;
                    } else if (location.equals(EMPTY_STRING)) {
                        location = null;
                    }
                }
                info.setLocation(location);
            } catch (Exception ignored) {
                // ignored
            }

        } else {
            info.setNamespace(defaultTargetNamespace);
        }
        if (!info.isElementFormQualified() ){
            isDefaultNamespaceAllowed = false;
        }
        return info;
    }

    public Map<String, TypeInfo> getTypeInfos() {
        return typeInfos;
    }

    public List<JavaClass> getTypeInfoClasses() {
        return typeInfoClasses;
    }

    public Map<String, QName> getUserDefinedSchemaTypes() {
        return userDefinedSchemaTypes;
    }

    public QName getQNameForProperty(Property property, String defaultName, JavaHasAnnotations element, NamespaceInfo namespaceInfo, TypeInfo info) {
        String uri = info.getClassNamespace();
        String name = XMLProcessor.DEFAULT;
        String namespace = XMLProcessor.DEFAULT;
        QName qName = null;

        if(property.isMap()){
            isDefaultNamespaceAllowed = false;
        }

        if (helper.isAnnotationPresent(element, XmlAttribute.class)) {
            XmlAttribute xmlAttribute = (XmlAttribute) helper.getAnnotation(element, XmlAttribute.class);
            name = xmlAttribute.name();
            namespace = xmlAttribute.namespace();

            if (name.equals(XMLProcessor.DEFAULT)) {
                name = defaultName;
                try {
                    name = info.getXmlNameTransformer().transformAttributeName(name);
                } catch (Exception ex) {
                    throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(name, info.getXmlNameTransformer().getClass().getName(), ex);
                }
            }

            if (!namespace.equals(XMLProcessor.DEFAULT)) {
                qName = new QName(namespace, name);
                isDefaultNamespaceAllowed = false;
            } else {
                if (namespaceInfo.isAttributeFormQualified()) {
                    qName = new QName(uri, name);
                    isDefaultNamespaceAllowed = false;
                } else {
                    qName = new QName(name);
                }
            }
        } else {
            if (helper.isAnnotationPresent(element, XmlElement.class)) {
                XmlElement xmlElement = (XmlElement) helper.getAnnotation(element, XmlElement.class);
                name = xmlElement.name();
                namespace = xmlElement.namespace();
            }
            if (property.isMap() && helper.isAnnotationPresent(element, XmlElementWrapper.class)) {
                XmlElementWrapper xmlElementWrapper = (XmlElementWrapper) helper.getAnnotation(element, XmlElementWrapper.class);
                name = xmlElementWrapper.name();
                namespace = xmlElementWrapper.namespace();
            }

            if (name.equals(XMLProcessor.DEFAULT)) {
                name = defaultName;

                try {
                    name = info.getXmlNameTransformer().transformElementName(name);
                } catch (Exception ex) {
                    throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(name, info.getXmlNameTransformer().getClass().getName(), ex);
                }
            }

            if (!namespace.equals(XMLProcessor.DEFAULT)) {
                qName = new QName(namespace, name);
                if (namespace.equals(Constants.EMPTY_STRING)) {
                    isDefaultNamespaceAllowed = false;
                }
            } else {
                if (namespaceInfo.isElementFormQualified()) {
                    qName = new QName(uri, name);
                } else {
                    qName = new QName(name);
                }
            }
        }
        return qName;
    }

    public Map<String, PackageInfo> getPackageToPackageInfoMappings() {
        return packageToPackageInfoMappings;
    }

    /**
     * Add a package name/NamespaceInfo entry to the map. This method will
     * lazy-load the map if necessary.
     */
    public void addPackageToNamespaceMapping(String packageName, NamespaceInfo nsInfo) {
      PackageInfo info = getPackageInfoWithLazyInit(packageName);
        info.setNamespaceInfo(nsInfo);
    }

    /**
     * Add a package name/XmlElementNillable entry to the map. This method will
     * lazy-load the map if necessary.
     */
    public void addPackageToXmlElementNillable(String packageName, org.eclipse.persistence.jaxb.xmlmodel.XmlElementNillable xmlElementNillable) {
        XmlNillableInfo info = getXmlNillableInfoWithLazyInit(packageName);
        info.setXmlElementNillable(xmlElementNillable);
    }

    /**
     * Add a package name/XmlNullPolicy entry to the map. This method will
     * lazy-load the map if necessary.
     */
    public void addPackageToXmlNullPolicy(String packageName, org.eclipse.persistence.jaxb.xmlmodel.XmlNullPolicy xmlNullPolicy) {
        XmlNillableInfo info = getXmlNillableInfoWithLazyInit(packageName);
        info.setXmlNullPolicy(xmlNullPolicy);
    }

    private XmlNillableInfo getXmlNillableInfoWithLazyInit(String packageName) {
        if (packageToXmlNillableInfoMappings == null) {
            packageToXmlNillableInfoMappings = new HashMap<String, XmlNillableInfo>();
        }
        XmlNillableInfo info = packageToXmlNillableInfoMappings.get(packageName);
        if (info == null) {
            info = new XmlNillableInfo();
            packageToXmlNillableInfoMappings.put(packageName, info);
        }
        return info;
    }

    private PackageInfo getPackageInfoWithLazyInit(String packageName) {
        if (packageToPackageInfoMappings == null) {
            packageToPackageInfoMappings = new HashMap<String, PackageInfo>();
        }
        PackageInfo info = packageToPackageInfoMappings.get(packageName);
        if (info == null) {
            info = new PackageInfo();
            packageToPackageInfoMappings.put(packageName, info);
        }
        return info;
    }

    public void addPackageToPackageInfoMapping(String packageName, PackageInfo packageInfo) {
        if(packageToPackageInfoMappings == null) {
            packageToPackageInfoMappings = new HashMap<String, PackageInfo>();
        }
        packageToPackageInfoMappings.put(packageName, packageInfo);
    }

    public PackageInfo getPackageInfoForPackage(JavaClass javaClass) {
        String packageName = javaClass.getPackageName();
        PackageInfo packageInfo = packageToPackageInfoMappings.get(packageName);
        if (packageInfo == null) {
            packageInfo = getPackageInfoForPackage(javaClass.getPackage(), packageName);
        }
        return packageInfo;
    }

    public PackageInfo getPackageInfoForPackage(JavaPackage pack, String packageName) {
        PackageInfo packageInfo = packageToPackageInfoMappings.get(packageName);
        if (packageInfo == null) {
            XmlSchema xmlSchema = (XmlSchema) helper.getAnnotation(pack, XmlSchema.class);
            packageInfo = new PackageInfo();
            NamespaceInfo   namespaceInfo = processNamespaceInformation(xmlSchema);

            packageInfo.setNamespaceInfo(namespaceInfo);

            // if it's still null, generate based on package name
            if (namespaceInfo.getNamespace() == null) {
                namespaceInfo.setNamespace(EMPTY_STRING);
            }
            if (helper.isAnnotationPresent(pack, XmlAccessorType.class)) {
                XmlAccessorType xmlAccessorType = (XmlAccessorType) helper.getAnnotation(pack, XmlAccessorType.class);
                packageInfo.setAccessType(XmlAccessType.fromValue(xmlAccessorType.value().name()));
            }
            if (helper.isAnnotationPresent(pack, XmlAccessorOrder.class)) {
                XmlAccessorOrder xmlAccessorOrder = (XmlAccessorOrder) helper.getAnnotation(pack, XmlAccessorOrder.class);
                packageInfo.setAccessOrder(XmlAccessOrder.fromValue(xmlAccessorOrder.value().name()));
            }
            if (CompilerHelper.ACCESSOR_FACTORY_ANNOTATION_CLASS != null && helper.isAnnotationPresent(pack, CompilerHelper.ACCESSOR_FACTORY_ANNOTATION_CLASS)) {
                Annotation xmlAccessorFactory = helper.getAnnotation(pack, CompilerHelper.ACCESSOR_FACTORY_ANNOTATION_CLASS);
                Class xmlAccessorFactoryClass = null;
                try {
                    xmlAccessorFactoryClass = PrivilegedAccessHelper.invokeMethod(CompilerHelper.ACCESSOR_FACTORY_VALUE_METHOD, xmlAccessorFactory, new Object[]{});
                    packageInfo.setAccessorFactory(new AccessorFactoryWrapper(PrivilegedAccessHelper.newInstanceFromClass(xmlAccessorFactoryClass)));
                } catch (Exception ex) {
                    throw JAXBException.errorInstantiatingAccessorFactory(xmlAccessorFactoryClass, ex);
                }
            } else if (CompilerHelper.OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS != null && helper.isAnnotationPresent(pack, CompilerHelper.OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS)) {
                Annotation xmlAccessorFactory = helper.getAnnotation(pack, CompilerHelper.OLD_ACCESSOR_FACTORY_ANNOTATION_CLASS);
                Class xmlAccessorFactoryClass = null;
                try {
                    xmlAccessorFactoryClass = PrivilegedAccessHelper.invokeMethod(CompilerHelper.OLD_ACCESSOR_FACTORY_VALUE_METHOD, xmlAccessorFactory, new Object[]{});
                    packageInfo.setAccessorFactory(new AccessorFactoryWrapper(PrivilegedAccessHelper.newInstanceFromClass(xmlAccessorFactoryClass)));
                } catch (Exception ex) {
                    throw JAXBException.errorInstantiatingAccessorFactory(xmlAccessorFactoryClass, ex);
                }
            } else if (CompilerHelper.INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS != null && helper.isAnnotationPresent(pack, CompilerHelper.INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS)) {
                Annotation xmlAccessorFactory = helper.getAnnotation(pack, CompilerHelper.INTERNAL_ACCESSOR_FACTORY_ANNOTATION_CLASS);
                Class xmlAccessorFactoryClass = null;
                try {
                    xmlAccessorFactoryClass = PrivilegedAccessHelper.invokeMethod(CompilerHelper.INTERNAL_ACCESSOR_FACTORY_VALUE_METHOD, xmlAccessorFactory, new Object[]{});
                    packageInfo.setAccessorFactory(new AccessorFactoryWrapper(PrivilegedAccessHelper.newInstanceFromClass(xmlAccessorFactoryClass)));
                } catch (Exception ex) {
                    throw JAXBException.errorInstantiatingAccessorFactory(xmlAccessorFactoryClass, ex);
                }
            }
            packageToPackageInfoMappings.put(packageName, packageInfo);
        }
        return packageInfo;
    }

    public NamespaceInfo findInfoForNamespace(String namespace) {
        for(PackageInfo next:this.packageToPackageInfoMappings.values()) {
            String nextUri = next.getNamespace();
            if(nextUri == null) {
                nextUri = Constants.EMPTY_STRING;
            }
            if(namespace == null) {
                namespace = Constants.EMPTY_STRING;
            }

            if(nextUri.equals(namespace)) {
                return next.getNamespaceInfo();
            }
        }
        return null;
    }

    void checkForCallbackMethods() {
        JavaClass unmarshallerCls = helper.getJavaClass(Unmarshaller.class);
        JavaClass marshallerCls = helper.getJavaClass(Marshaller.class);
        JavaClass objectCls = helper.getJavaClass(Object.class);
        JavaClass[] unmarshalParams = new JavaClass[] { unmarshallerCls, objectCls };
        JavaClass[] marshalParams = new JavaClass[] { marshallerCls };

        for (JavaClass next : typeInfoClasses) {
            if (next == null) {
                continue;
            }

            UnmarshalCallback unmarshalCallback = null;
            MarshalCallback marshalCallback = null;
            // look for before unmarshal callback
            if (next.getMethod("beforeUnmarshal", unmarshalParams) != null) {
                unmarshalCallback = new UnmarshalCallback();
                unmarshalCallback.setDomainClassName(next.getQualifiedName());
                unmarshalCallback.setHasBeforeUnmarshalCallback();
            }
            // look for after unmarshal callback
            if (next.getMethod("afterUnmarshal", unmarshalParams) != null) {
                if (unmarshalCallback == null) {
                    unmarshalCallback = new UnmarshalCallback();
                    unmarshalCallback.setDomainClassName(next.getQualifiedName());
                }
                unmarshalCallback.setHasAfterUnmarshalCallback();
            }
            // if before/after unmarshal callback was found, add the callback to
            // the list
            if (unmarshalCallback != null) {
                if (this.unmarshalCallbacks == null) {
                    this.unmarshalCallbacks = new HashMap<String, UnmarshalCallback>();
                }
                unmarshalCallbacks.put(next.getQualifiedName(), unmarshalCallback);
            }
            // look for before marshal callback
            if (next.getMethod("beforeMarshal", marshalParams) != null) {
                marshalCallback = new MarshalCallback();
                marshalCallback.setDomainClassName(next.getQualifiedName());
                marshalCallback.setHasBeforeMarshalCallback();
            }
            // look for after marshal callback
            if (next.getMethod("afterMarshal", marshalParams) != null) {
                if (marshalCallback == null) {
                    marshalCallback = new MarshalCallback();
                    marshalCallback.setDomainClassName(next.getQualifiedName());
                }
                marshalCallback.setHasAfterMarshalCallback();
            }
            // if before/after marshal callback was found, add the callback to
            // the list
            if (marshalCallback != null) {
                if (this.marshalCallbacks == null) {
                    this.marshalCallbacks = new HashMap<String, MarshalCallback>();
                }
                marshalCallbacks.put(next.getQualifiedName(), marshalCallback);
            }
        }
    }

    public Map<String, MarshalCallback> getMarshalCallbacks() {
        return this.marshalCallbacks;
    }

    public Map<String, UnmarshalCallback> getUnmarshalCallbacks() {
        return this.unmarshalCallbacks;
    }

    private void findAndProcessObjectFactory(JavaClass cls){
        //need to make sure objectfactory gets processed.
        try {
            String className =cls.getPackageName() + ".ObjectFactory";
            findAndProcessObjectFactory(className);
        } catch (JAXBException ignored) { /* ignored */}
    }

    void findAndProcessObjectFactory(String objectFactoryClassName){
        //need to make sure objectfactory gets processed.
        try {
            if(objectFactoryClassNames.contains(objectFactoryClassName)){
                return;
            }
            JavaClass javaClass = helper.getJavaClass(objectFactoryClassName);
            if (isXmlRegistry(javaClass)) {
                JavaClass[] processed = this.processObjectFactory(javaClass, new ArrayList<JavaClass>());
                preBuildTypeInfo(processed);
                buildTypeInfo(processed);
                updateGlobalElements(processed);
            }
        } catch (JAXBException ignored){ /* ignored */ }
    }

    public JavaClass[] processObjectFactory(JavaClass objectFactoryClass, List<JavaClass> classes) {

        String className = objectFactoryClass.getName();
        if(objectFactoryClassNames.contains(className)){
            return new JavaClass[0];
        }
        objectFactoryClassNames.add(className);
        // if there is an xml-registry from XML for this JavaClass, create a map
        // of method names to XmlElementDecl objects to simplify processing
        // later on in this method
        Map<String, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry.XmlElementDecl> elemDecls = new HashMap<String, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry.XmlElementDecl>();
        org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry xmlReg = xmlRegistries.get(objectFactoryClass.getQualifiedName());
        if (xmlReg != null) {
            // process xml-element-decl entries
            for (org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry.XmlElementDecl xmlElementDecl : xmlReg.getXmlElementDecl()) {
                // key each element-decl on method name
                elemDecls.put(xmlElementDecl.getJavaMethod(), xmlElementDecl);
            }
        }

        Collection methods = objectFactoryClass.getDeclaredMethods();
        Iterator methodsIter = methods.iterator();
        PackageInfo packageInfo = getPackageInfoForPackage(objectFactoryClass);
        while (methodsIter.hasNext()) {
            JavaMethod next = (JavaMethod) methodsIter.next();
            if (next.getName().startsWith(CREATE)) {
                JavaClass type = next.getReturnType();
                if (JAVAX_XML_BIND_JAXBELEMENT.equals(type.getName())) {
                    Object[] actualTypeArguments = type.getActualTypeArguments().toArray();
                    if (actualTypeArguments.length == 0) {
                        type = helper.getObjectClass();
                    } else {
                        type = (JavaClass) actualTypeArguments[0];
                    }
                    type = processXmlElementDecl(type, next, packageInfo, elemDecls);
                }else if (helper.getJaxbElementClass().isAssignableFrom(type)) {
                    this.factoryMethods.put(type.getRawName(), next);
                    type = processXmlElementDecl(type, next, packageInfo, elemDecls);
                } else {
                    this.factoryMethods.put(type.getRawName(), next);
                }
                if (!helper.isBuiltInJavaType(type) && !helper.classExistsInArray(type, classes)) {
                    classes.add(type);
                }
            }
        }

        if (classes.size() > 0) {
            classesToProcessPropertyTypes.addAll(classes);
            return classes.toArray(new JavaClass[classes.size()]);
        } else {
            return new JavaClass[0];
        }
    }

    private JavaClass processXmlElementDecl(JavaClass type, JavaMethod next, PackageInfo packageInfo, Map<String, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry.XmlElementDecl> elemDecls){
        JavaClass returnType = type;
        // if there's an XmlElementDecl for this method from XML, use it
        // - otherwise look for an annotation
        org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry.XmlElementDecl xmlEltDecl = elemDecls.get(next.getName());
        if (( xmlEltDecl != null) || helper.isAnnotationPresent(next, XmlElementDecl.class)) {
            QName qname;
            QName substitutionHead = null;
            String url;
            String localName;
            String defaultValue = null;
            Class scopeClass = jakarta.xml.bind.annotation.XmlElementDecl.GLOBAL.class;

            if (xmlEltDecl != null) {
                url = xmlEltDecl.getNamespace();
                localName = xmlEltDecl.getName();
                String scopeClassName = xmlEltDecl.getScope();
                if (!scopeClassName.equals(ELEMENT_DECL_GLOBAL)) {
                    JavaClass jScopeClass = helper.getJavaClass(scopeClassName);
                    if (jScopeClass != null) {
                        scopeClass = helper.getClassForJavaClass(jScopeClass);
                        if (scopeClass == null) {
                            scopeClass = jakarta.xml.bind.annotation.XmlElementDecl.GLOBAL.class;
                        }
                    }
                }
                if (!xmlEltDecl.getSubstitutionHeadName().equals(EMPTY_STRING)) {
                    String subHeadLocal = xmlEltDecl.getSubstitutionHeadName();
                    String subHeadNamespace = xmlEltDecl.getSubstitutionHeadNamespace();
                    if (subHeadNamespace.equals(XMLProcessor.DEFAULT)) {
                        subHeadNamespace = packageInfo.getNamespace();
                    }
                    substitutionHead = new QName(subHeadNamespace, subHeadLocal);
                }
                if (!(xmlEltDecl.getDefaultValue().length() == 1 && xmlEltDecl.getDefaultValue().startsWith(ELEMENT_DECL_DEFAULT))) {
                    defaultValue = xmlEltDecl.getDefaultValue();
                }
            } else {
                // there was no xml-element-decl for this method in XML,
                // so use the annotation
                XmlElementDecl elementDecl = (XmlElementDecl) helper.getAnnotation(next, XmlElementDecl.class);
                url = elementDecl.namespace();
                localName = elementDecl.name();
                scopeClass = elementDecl.scope();
                if (!elementDecl.substitutionHeadName().equals(EMPTY_STRING)) {
                    String subHeadLocal = elementDecl.substitutionHeadName();
                    String subHeadNamespace = elementDecl.substitutionHeadNamespace();
                    if (subHeadNamespace.equals(XMLProcessor.DEFAULT)) {
                        subHeadNamespace = packageInfo.getNamespace();
                    }

                    substitutionHead = new QName(subHeadNamespace, subHeadLocal);
                }
                if (!(elementDecl.defaultValue().length() == 1 && elementDecl.defaultValue().startsWith(ELEMENT_DECL_DEFAULT))) {
                    defaultValue = elementDecl.defaultValue();
                }
            }

            if (XMLProcessor.DEFAULT.equals(url)) {
                url = packageInfo.getNamespace();
            }
            if(Constants.EMPTY_STRING.equals(url)) {
                isDefaultNamespaceAllowed = false;
                qname = new QName(localName);
            }else{
                qname = new QName(url, localName);
            }

            boolean isList = false;
            if (JAVA_UTIL_LIST.equals(type.getName())) {
                isList = true;
                Collection args = type.getActualTypeArguments();
                if (args.size() > 0) {
                    type = (JavaClass) args.iterator().next();
                }
            }

            ElementDeclaration declaration = new ElementDeclaration(qname, type, type.getQualifiedName(), isList, scopeClass);
            if (substitutionHead != null) {
                declaration.setSubstitutionHead(substitutionHead);
            }
            if (defaultValue != null) {
                declaration.setDefaultValue(defaultValue);
            }

            if (helper.isAnnotationPresent(next, XmlJavaTypeAdapter.class)) {
                XmlJavaTypeAdapter typeAdapter = (XmlJavaTypeAdapter) helper.getAnnotation(next, XmlJavaTypeAdapter.class);
                Class typeAdapterClass = typeAdapter.value();
                declaration.setJavaTypeAdapterClass(typeAdapterClass);

                Class declJavaType = CompilerHelper.getTypeFromAdapterClass(typeAdapterClass);
                JavaClass adaptedType = helper.getJavaClass(declJavaType);
                declaration.setJavaType(adaptedType);
                declaration.setAdaptedJavaType(type);
                returnType = adaptedType;
            }
            if (helper.isAnnotationPresent(next, XmlMimeType.class)) {
                XmlMimeType mimeType = (XmlMimeType)helper.getAnnotation(next, XmlMimeType.class);
                declaration.setXmlMimeType(mimeType.value());
            }
            if (helper.isAnnotationPresent(next, XmlAttachmentRef.class)) {
                declaration.setXmlAttachmentRef(true);
            }
            Map<QName, ElementDeclaration> elements = getElementDeclarationsForScope(scopeClass.getName());
            if (elements == null) {
                elements = new HashMap<QName, ElementDeclaration>();
                this.elementDeclarations.put(scopeClass.getName(), elements);
            }
            if(elements.containsKey(qname)){
                throw JAXBException.duplicateElementName(qname);
            }

            elements.put(qname, declaration);
        }
        return returnType;
    }

    /**
     * Lazy load and return the map of global elements.
     *
     */
    public Map<QName, ElementDeclaration> getGlobalElements() {
        return this.elementDeclarations.get(XmlElementDecl.GLOBAL.class.getName());
    }

    public void updateGlobalElements(JavaClass[] classesToProcess) {
        // Once all the global element declarations have been created, make sure
        // that any ones that have
        // a substitution head set are added to the list of substitutable
        // elements on the declaration for that
        // head.

        // Look for XmlRootElement declarations
        for (JavaClass javaClass : classesToProcess) {
            TypeInfo info = typeInfos.get(javaClass.getQualifiedName());
            if (info == null) {
                continue;
            }
            if (!info.isTransient() && info.isSetXmlRootElement()) {
                org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement xmlRE = info.getXmlRootElement();
                NamespaceInfo namespaceInfo;
                namespaceInfo = getPackageInfoForPackage(javaClass).getNamespaceInfo();

                String elementName = xmlRE.getName();
                if (elementName.equals(XMLProcessor.DEFAULT) || elementName.equals(EMPTY_STRING)) {
                    XMLNameTransformer transformer = info.getXmlNameTransformer();
                    try {
                        elementName = transformer.transformRootElementName(javaClass.getName());
                    } catch (Exception ex) {
                        throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(javaClass.getName(), info.getXmlNameTransformer().getClass().getName(), ex);
                    }

                }
                String rootNamespace = xmlRE.getNamespace();
                QName rootElemName = null;
                if (rootNamespace.equals(XMLProcessor.DEFAULT)) {
                    if (namespaceInfo == null) {
                        rootElemName = new QName(elementName);
                    } else {
                        String rootNS = namespaceInfo.getNamespace();
                        rootElemName = new QName(rootNS, elementName);
                        if (rootNS.equals(Constants.EMPTY_STRING)) {
                            isDefaultNamespaceAllowed = false;
                        }
                    }
                } else {
                    rootElemName = new QName(rootNamespace, elementName);
                    if (rootNamespace.equals(Constants.EMPTY_STRING)) {
                        isDefaultNamespaceAllowed = false;
                    }
                }
                ElementDeclaration declaration = new ElementDeclaration(rootElemName, javaClass, javaClass.getQualifiedName(), false);
                declaration.setIsXmlRootElement(true);
                addGlobalElement(rootElemName, declaration);
                this.xmlRootElements.put(javaClass.getQualifiedName(), declaration);
            }
        }

        for (QName next : this.getGlobalElements().keySet()) {
            ElementDeclaration nextDeclaration = this.getGlobalElements().get(next);
            QName substitutionHead = nextDeclaration.getSubstitutionHead();
            while (substitutionHead != null) {
                ElementDeclaration rootDeclaration = this.getGlobalElements().get(substitutionHead);
                rootDeclaration.addSubstitutableElement(nextDeclaration);
                if (rootDeclaration.getSubstitutionHead() != null && rootDeclaration.getSubstitutionHead().equals(substitutionHead)) {
                    // Break the loop if substitutionHead equals rootDeclaration's substitutionHead
                    // (XmlElementDecl's substitutionHeadName == name)
                    substitutionHead = null;
                } else {
                    substitutionHead = rootDeclaration.getSubstitutionHead();
                }
            }
        }
    }

    private void addReferencedElement(Property property, ElementDeclaration referencedElement) {
        property.addReferencedElement(referencedElement);
        if (referencedElement.getSubstitutableElements() != null && referencedElement.getSubstitutableElements().size() > 0) {
            for (ElementDeclaration substitutable : referencedElement.getSubstitutableElements()) {
                if (substitutable != referencedElement) {
                    addReferencedElement(property, substitutable);
                }
            }
        }
    }

    /**
     * Returns true if the field or method passed in is annotated with JAXB
     * annotations.
     */
    private boolean hasJAXBAnnotations(JavaHasAnnotations elem) {
        if(elem == null){
            return false;
        }
        List annotations = (List<JavaAnnotation>) elem.getAnnotations();
        if (annotations == null || annotations.isEmpty()) {
            return false;
        }
        for (Object annotation : annotations) {
            String nextName = ((JavaAnnotation) annotation).getName();
            if (nextName.startsWith(JAVAX_XML_BIND_ANNOTATION)
                    || nextName.startsWith(OXM_ANNOTATIONS)
                    || nextName.equals(CompilerHelper.XML_LOCATION_ANNOTATION_NAME)
                    || nextName.equals(CompilerHelper.INTERNAL_XML_LOCATION_ANNOTATION_NAME)) {
                return true;
            }
        }
        return false;
    }


    private void validatePropOrderForInfo(TypeInfo info) {
        if (info.isTransient()) {
            return;
        }
        if(info.getXmlVirtualAccessMethods() != null) {
            return;
        }
        // Ensure that all properties in the propOrder list actually exist
        String[] propOrder = info.getPropOrder();
        int propOrderLength = propOrder.length;
        if (propOrderLength > 0) {
            for (int i = 1; i < propOrderLength; i++) {
                String nextPropName = propOrder[i];
                if (!nextPropName.equals(EMPTY_STRING) && !info.getPropertyNames().contains(nextPropName)) {
                    throw JAXBException.nonExistentPropertyInPropOrder(nextPropName, info.getJavaClassName());
                }
            }
        }
    }

    private void validateXmlValueFieldOrProperty(JavaClass cls, Property property) {
        JavaClass ptype = property.getActualType();
        String propName = property.getPropertyName();
        JavaClass parent = cls.getSuperclass();

        while (parent != null && !(parent.getQualifiedName().equals(JAVA_LANG_OBJECT))) {
            if (!useXmlValueExtension(property)) {
                throw JAXBException.propertyOrFieldCannotBeXmlValue(propName, cls.getQualifiedName());
            } else {
                TypeInfo parentTypeInfo = typeInfos.get(parent.getQualifiedName());
                if(hasElementMappedProperties(parentTypeInfo)) {
                    throw JAXBException.propertyOrFieldCannotBeXmlValue(propName, cls.getQualifiedName());
                }
                parent = parent.getSuperclass();
            }
        }

        QName schemaQName = getSchemaTypeOrNullFor(ptype);
        if (schemaQName == null) {
            TypeInfo refInfo = processReferencedClass(ptype);
            if (refInfo != null && !refInfo.isEnumerationType() && refInfo.getXmlValueProperty() == null) {
                throw JAXBException.invalidTypeForXmlValueField(propName, cls.getQualifiedName());
            }
        }
    }

    private boolean useXmlValueExtension(Property property) {
        return MOXySystemProperties.xmlValueExtension || helper.isAnnotationPresent(property.getElement(), XmlValueExtension.class) || property.isXmlValueExtension();
    }

    private boolean hasElementMappedProperties(TypeInfo typeInfo) {
        for(Property property : typeInfo.getPropertyList()) {
            if(!(property.isTransient()|| property.isAttribute() || property.isAnyAttribute())) {
                return true;
            }
        }
        return false;
    }

    private void validateXmlAttributeFieldOrProperty(TypeInfo tInfo, Property property) {
        // Check that @XmlAttribute references a Java type that maps to text in XML
        JavaClass ptype = property.getActualType();
        TypeInfo refInfo = typeInfos.get(ptype.getQualifiedName());
        if (refInfo != null) {
            if (!refInfo.isPostBuilt()) {
                postBuildTypeInfo(new JavaClass[] { ptype });
            }
            if (!refInfo.isEnumerationType()) {
                JavaClass parent = ptype.getSuperclass();
                boolean hasMapped = false;
                while (parent != null) {
                    hasMapped = hasTextMapping(refInfo);
                    if (hasMapped || parent.getQualifiedName().equals(JAVA_LANG_OBJECT)) {
                        break;
                    }
                    refInfo = typeInfos.get(parent.getQualifiedName());
                    parent = parent.getSuperclass();
                }
                if (!hasMapped) {
                    String propName = property.getPropertyName();
                    String typeName = tInfo.getJavaClassName();
                    String refTypeName = refInfo.getJavaClassName();
                    throw org.eclipse.persistence.exceptions.JAXBException.mustMapToText(propName, typeName, refTypeName);
                }
            }
        }
    }

    private boolean hasTextMapping(TypeInfo tInfo) {
        Collection<Property> props = tInfo.getProperties().values();
        for (Property property : props) {
            if (property.isAttribute()) {
                JavaClass ptype = property.getActualType();
                TypeInfo refInfo = typeInfos.get(ptype.getQualifiedName());
                if (refInfo != null && refInfo != tInfo) {
                    return hasTextMapping(refInfo);
                }
            }
        }

        boolean hasXmlId = (tInfo.getIDProperty() != null && !tInfo.getIDProperty().isTransient());
        boolean hasXmlValue = (tInfo.getXmlValueProperty() != null && !tInfo.getXmlValueProperty().isTransient());
        if (hasXmlValue) {
            // Ensure there is an @XmlValue property and nothing else
            hasXmlValue = CompilerHelper.isSimpleType(tInfo);
        }

        return (hasXmlValue || hasXmlId);
    }

    private Class generateWrapperForMapClass(JavaClass mapClass, JavaClass keyClass, JavaClass valueClass, TypeMappingInfo typeMappingInfo) {
        String packageName = JAXB_DEV;
        NamespaceResolver combinedNamespaceResolver = new NamespaceResolver();
        if (!helper.isBuiltInJavaType(keyClass)) {
            String keyPackageName = keyClass.getPackageName();
            packageName = packageName + DOT_CHR + keyPackageName;
            NamespaceInfo keyNamespaceInfo = getPackageInfoForPackage(keyClass).getNamespaceInfo();
            if (keyNamespaceInfo != null) {
                java.util.Vector<Namespace> namespaces = keyNamespaceInfo.getNamespaceResolver().getNamespaces();
                for (Namespace n : namespaces) {
                    combinedNamespaceResolver.put(n.getPrefix(), n.getNamespaceURI());
                }

            }
        }

        if (!helper.isBuiltInJavaType(valueClass)) {
            String valuePackageName = valueClass.getPackageName();
            packageName = packageName + DOT_CHR + valuePackageName;
            NamespaceInfo valueNamespaceInfo = getPackageInfoForPackage(valueClass).getNamespaceInfo();
            if (valueNamespaceInfo != null) {
                java.util.Vector<Namespace> namespaces = valueNamespaceInfo.getNamespaceResolver().getNamespaces();
                for (Namespace n : namespaces) {
                    combinedNamespaceResolver.put(n.getPrefix(), n.getNamespaceURI());
                }
            }
        }
        String namespace = this.defaultTargetNamespace;
        if (namespace == null) {
            namespace = EMPTY_STRING;
        }
        PackageInfo packageInfo = packageToPackageInfoMappings.get(mapClass.getPackageName());
        if (packageInfo == null) {
            packageInfo = getPackageToPackageInfoMappings().get(packageName);
        } else {
            if (packageInfo.getNamespace() != null) {
                namespace = packageInfo.getNamespace();
            }
            getPackageToPackageInfoMappings().put(packageName, packageInfo);
        }
        if (packageInfo == null) {
            packageInfo = new PackageInfo();
            packageInfo.setNamespaceInfo(new NamespaceInfo());
            packageInfo.setNamespace(namespace);
            packageInfo.setNamespaceResolver(combinedNamespaceResolver);

            getPackageToPackageInfoMappings().put(packageName, packageInfo);
        }

        int beginIndex = keyClass.getName().lastIndexOf(DOT_CHR) + 1;
        String keyName = keyClass.getName().substring(beginIndex);
        int dollarIndex = keyName.indexOf(DOLLAR_SIGN_CHR);
        if (dollarIndex > -1) {
            keyName = keyName.substring(dollarIndex + 1);
        }

        beginIndex = valueClass.getName().lastIndexOf(DOT_CHR) + 1;
        String valueName = valueClass.getName().substring(beginIndex);
        dollarIndex = valueName.indexOf(DOLLAR_SIGN_CHR);
        if (dollarIndex > -1) {
            valueName = valueName.substring(dollarIndex + 1);
        }
        String collectionClassShortName = mapClass.getRawName().substring(mapClass.getRawName().lastIndexOf(DOT_CHR) + 1);
        String suggestedClassName = keyName + valueName + collectionClassShortName;

        String qualifiedClassName = packageName + DOT_CHR + suggestedClassName;
        qualifiedClassName = getNextAvailableClassName(qualifiedClassName);

        String qualifiedInternalClassName = qualifiedClassName.replace(DOT_CHR, SLASH_CHR);
        String internalKeyName = keyClass.getQualifiedName().replace(DOT_CHR, SLASH_CHR);
        String internalValueName = valueClass.getQualifiedName().replace(DOT_CHR, SLASH_CHR);

        Type mapType = Type.getType(L + mapClass.getRawName().replace(DOT_CHR, SLASH_CHR) + SEMI_COLON);

        EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();

        String sig = "Lorg/eclipse/persistence/internal/jaxb/many/MapValue<L" + mapType.getInternalName() + "<L" + internalKeyName + ";L" + internalValueName + ";>;>;";
        cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, qualifiedInternalClassName, sig, "org/eclipse/persistence/internal/jaxb/many/MapValue", null);

        // Write Field: @... public Map entry
        String fieldSig = L + mapType.getInternalName() + "<L" + internalKeyName + ";L" + internalValueName + ";>;";
        FieldVisitor fv = cw.visitField(Opcodes.ACC_PUBLIC, "entry", L + mapType.getInternalName() + SEMI_COLON, fieldSig, null);
        fv.visitAnnotation(Type.getDescriptor(XmlElement.class), true);
        if (typeMappingInfo != null) {
            Annotation[] annotations = typeMappingInfo.getAnnotations();
            if (annotations != null) {
                for (Annotation nextAnnotation : annotations) {
                    if (nextAnnotation != null && !(nextAnnotation instanceof XmlElement) && !(nextAnnotation instanceof XmlJavaTypeAdapter)) {
                        String annotationClassName = nextAnnotation.annotationType().getName();
                        AnnotationVisitor av = fv.visitAnnotation(L + annotationClassName.replace(DOT_CHR, SLASH_CHR) + SEMI_COLON, true);
                        for (Method next : nextAnnotation.annotationType().getDeclaredMethods()) {
                            try {
                                Object nextValue = next.invoke(nextAnnotation, new Object[] { });
                                if (nextValue instanceof Class) {
                                    Type nextType = Type.getType(L + ((Class) nextValue).getName().replace(DOT_CHR, SLASH_CHR) + SEMI_COLON);
                                    nextValue = nextType;
                                }
                                av.visit(next.getName(), nextValue);
                            } catch (InvocationTargetException ignored) {
                                // ignore the invocation target exception here.
                            } catch (IllegalAccessException ignored) {
                                // ignore the illegal access exception here.
                            }
                        }
                        av.visitEnd();
                    }
                }
            }
        }
        fv.visitEnd();

        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, "org/eclipse/persistence/internal/jaxb/many/MapValue", "<init>", "()V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        // Write: @XmlTransient public void setItem(???)
        String methodSig = "(L" + mapType.getInternalName() + "<L" + internalKeyName + ";L" + internalValueName + ";>;)V";
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setItem", "(L" + mapType.getInternalName() + ";)V", methodSig, null);
        // TODO: Verify that we really want to put @XmlTranient on setItem
        // method
        mv.visitAnnotation("Ljakarta/xml/bind/annotation/XmlTransient;", true);
        Label l0 = new Label();
        mv.visitLabel(l0);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitFieldInsn(Opcodes.PUTFIELD, qualifiedInternalClassName, "entry", L + mapType.getInternalName() + SEMI_COLON);
        mv.visitInsn(Opcodes.RETURN);
        Label l1 = new Label();
        mv.visitLabel(l1);

        // Replacement?:LocalVariableTypeTableAttribute cvAttr = new
        // LocalVariableTypeTableAttribute();
        // mv.visitAttribute(cvAttr);

        mv.visitMaxs(2, 2);
        mv.visitEnd();

        // Write @XmlTransient public ??? getItem()
        methodSig = "()L" + mapType.getInternalName() + "<L" + internalKeyName + ";L" + internalValueName + ";>;";
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getItem", "()L" + mapType.getInternalName() + SEMI_COLON, methodSig, null);
        mv.visitAnnotation("Ljakarta/xml/bind/annotation/XmlTransient;", true);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitFieldInsn(Opcodes.GETFIELD, qualifiedInternalClassName, "entry", L + mapType.getInternalName() + SEMI_COLON);
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "getItem", "()Ljava/lang/Object;", null, null);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, qualifiedInternalClassName, "getItem", "()L" + mapType.getInternalName() + SEMI_COLON, false);
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        mv = cw.visitMethod(Opcodes.ACC_PUBLIC + Opcodes.ACC_BRIDGE + Opcodes.ACC_SYNTHETIC, "setItem", "(Ljava/lang/Object;)V", null, null);
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitTypeInsn(Opcodes.CHECKCAST, mapType.getInternalName());
        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, qualifiedInternalClassName, "setItem", "(L" + mapType.getInternalName() + ";)V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 2);
        mv.visitEnd();

        // Write @XmlType(namespace)
        AnnotationVisitor av = cw.visitAnnotation("Ljakarta/xml/bind/annotation/XmlType;", true);
        av.visit("namespace", namespace);

        cw.visitEnd();

        byte[] classBytes = cw.toByteArray();
        return generateClassFromBytes(qualifiedClassName, classBytes);
    }

    private Class generateWrapperForArrayClass(JavaClass arrayClass, TypeMappingInfo typeMappingInfo, Class xmlElementType, List<JavaClass> classesToProcess) {
        JavaClass componentClass = null;
        if (typeMappingInfo != null && xmlElementType != null) {
            componentClass = helper.getJavaClass(xmlElementType);
        } else {
            componentClass = arrayClass.getComponentType();
        }
        if (componentClass.isArray()) {
            Class nestedArrayClass = arrayClassesToGeneratedClasses.get(componentClass.getName());
            if (nestedArrayClass == null) {
                nestedArrayClass = generateWrapperForArrayClass(componentClass, typeMappingInfo, xmlElementType, classesToProcess);
                arrayClassesToGeneratedClasses.put(componentClass.getName(), nestedArrayClass);
                classesToProcess.add(helper.getJavaClass(nestedArrayClass));
            }
            return generateArrayValue(arrayClass, helper.getJavaClass(nestedArrayClass), helper.getJavaClass(nestedArrayClass), typeMappingInfo);
        } else {
            return generateArrayValue(arrayClass, componentClass, componentClass, typeMappingInfo);
        }
    }

    private Class generateArrayValue(JavaClass arrayClass, JavaClass componentClass, JavaClass nestedClass, TypeMappingInfo typeMappingInfo) {
        String packageName;
        String qualifiedClassName;
        QName qName = null;
        if (helper.getJavaClass(ManyValue.class).isAssignableFrom(componentClass)) {
            packageName = componentClass.getPackageName();
            qualifiedClassName = nestedClass.getQualifiedName() + ARRAY_CLASS_NAME_SUFFIX;
        } else {
            if (componentClass.isPrimitive()) {
                packageName = ARRAY_PACKAGE_NAME;
                qualifiedClassName = packageName + DOT_CHR + componentClass.getName() + ARRAY_CLASS_NAME_SUFFIX;
            } else {
                packageName = ARRAY_PACKAGE_NAME + DOT_CHR + componentClass.getPackageName();
                if (componentClass.isMemberClass()) {
                    qualifiedClassName = componentClass.getName();
                    qualifiedClassName = qualifiedClassName.substring(qualifiedClassName.indexOf(DOLLAR_SIGN_CHR) + 1);
                    qualifiedClassName = ARRAY_PACKAGE_NAME + DOT_CHR + componentClass.getPackageName() + DOT_CHR + qualifiedClassName + ARRAY_CLASS_NAME_SUFFIX;
                } else {
                    qualifiedClassName = ARRAY_PACKAGE_NAME + DOT_CHR + componentClass.getQualifiedName() + ARRAY_CLASS_NAME_SUFFIX;
                }
            }

            if (componentClass.isPrimitive() || helper.isBuiltInJavaType(componentClass)) {
                qName = (QName) helper.getXMLToJavaTypeMap().get(componentClass.getQualifiedName());
                if(null != qName) {
                    packageName = ARRAY_PACKAGE_NAME;
                    qualifiedClassName = ARRAY_PACKAGE_NAME + DOT_CHR + qName.getLocalPart() + ARRAY_CLASS_NAME_SUFFIX;
                }
                PackageInfo namespaceInfo = getPackageToPackageInfoMappings().get(packageName);
                if (namespaceInfo == null) {
                    namespaceInfo = new PackageInfo();
                    namespaceInfo.setNamespaceInfo(new NamespaceInfo());
                    namespaceInfo.setNamespace(ARRAY_NAMESPACE);
                    namespaceInfo.setNamespaceResolver(new NamespaceResolver());
                    getPackageToPackageInfoMappings().put(packageName, namespaceInfo);
                }
            } else {
                PackageInfo namespaceInfo = getPackageInfoForPackage(componentClass.getPackage(), componentClass.getPackageName());
                getPackageToPackageInfoMappings().put(packageName, namespaceInfo);
            }
        }

        try {
            String qualifiedInternalClassName = qualifiedClassName.replace(DOT_CHR, SLASH_CHR);
            if (helper.getJavaClass(ManyValue.class).isAssignableFrom(componentClass)) {
                return generateClassFromBytes(qualifiedClassName, generateMultiDimensionalManyValueClass(typeMappingInfo, null, MultiDimensionalArrayValue.class, qualifiedInternalClassName, componentClass, arrayClass.getComponentType()));
            } else {
                return generateClassFromBytes(qualifiedClassName, generateManyValue(typeMappingInfo, null, ArrayValue.class, qualifiedInternalClassName, componentClass, componentClass));
            }
        } catch(LinkageError e) {
            if(null != qName) {
                throw JAXBException.nameCollision(qName.getNamespaceURI(), qName.getLocalPart());
            }
            throw e;
        }
    }

    private JavaClass getObjectType(JavaClass javaClass) {
        if (javaClass.isPrimitive()) {
            String primitiveClassName = javaClass.getRawName();
            Class primitiveClass = getPrimitiveClass(primitiveClassName);
            return helper.getJavaClass(getObjectClass(primitiveClass));
        }
        return javaClass;
    }

    private Class generateCollectionValue(JavaClass collectionClass, TypeMappingInfo typeMappingInfo, Class xmlElementType, List<JavaClass> classesToProcess) {

        JavaClass componentClass;

        if (typeMappingInfo != null && xmlElementType != null) {
            componentClass = helper.getJavaClass(xmlElementType);
        } else{
            Collection args = collectionClass.getActualTypeArguments();
            if(args.size() >0 ){
                componentClass = ((JavaClass) args.toArray()[0]);
            }else{
                componentClass = helper.getJavaClass(Object.class);
            }
        }

        boolean multiDimensional = false;
        if (componentClass.isPrimitive()) {
            Class primitiveClass = getPrimitiveClass(componentClass.getRawName());
            componentClass = helper.getJavaClass(getObjectClass(primitiveClass));
        } else if(helper.getJavaClass(Collection.class).isAssignableFrom(componentClass)) {
            multiDimensional = true;
            java.lang.reflect.Type nestedCollectionType = getNestedCollectionType(typeMappingInfo);
            Class nestedCollectionClass = collectionClassesToGeneratedClasses.get(nestedCollectionType);
            if (nestedCollectionClass == null) {
                nestedCollectionClass = generateCollectionValue(componentClass, typeMappingInfo, xmlElementType, classesToProcess);
                collectionClassesToGeneratedClasses.put(nestedCollectionType, nestedCollectionClass);
                classesToProcess.add(helper.getJavaClass(nestedCollectionClass));
            }
            componentClass = helper.getJavaClass(nestedCollectionClass);
        } else if(componentClass.isArray()) {
            if(componentClass.getName().equals("[B")) {
                multiDimensional = false;
            } else {
                multiDimensional = true;
                Class nestedArrayClass = arrayClassesToGeneratedClasses.get(componentClass.getName());
                if (nestedArrayClass == null) {
                    nestedArrayClass = generateWrapperForArrayClass(componentClass, typeMappingInfo, xmlElementType, classesToProcess);
                    arrayClassesToGeneratedClasses.put(componentClass.getName(), nestedArrayClass);
                }
                componentClass = helper.getJavaClass(nestedArrayClass);
            }
        }

        PackageInfo packageInfo = packageToPackageInfoMappings.get(collectionClass.getPackageName());

        String namespace = EMPTY_STRING;
        if (this.defaultTargetNamespace != null) {
            namespace = this.defaultTargetNamespace;
        }

        PackageInfo componentNamespaceInfo = getPackageInfoForPackage(componentClass);
        String packageName = componentClass.getPackageName();
        packageName = "jaxb.dev.java.net." + packageName;
        if (packageInfo == null) {
            packageInfo = getPackageToPackageInfoMappings().get(packageName);
        } else {
            getPackageToPackageInfoMappings().put(packageName, packageInfo);
            if (packageInfo.getNamespace() != null) {
                namespace = packageInfo.getNamespace();
            }
        }
        if (packageInfo == null) {
            if (componentNamespaceInfo != null) {
                packageInfo = componentNamespaceInfo;
            } else {
                packageInfo = new PackageInfo();
                packageInfo.setNamespaceInfo(new NamespaceInfo());
                packageInfo.setNamespaceResolver(new NamespaceResolver());
            }
            getPackageToPackageInfoMappings().put(packageName, packageInfo);
        }

        String name = componentClass.getName();
        if("[B".equals(name)) {
            name = "byteArray";
        }

        int beginIndex = name.lastIndexOf(DOT_CHR) + 1;
        name = name.substring(beginIndex);
        int dollarIndex = name.indexOf(DOLLAR_SIGN_CHR);
        if (dollarIndex > -1) {
            name = name.substring(dollarIndex + 1);
        }
        String collectionClassRawName = collectionClass.getRawName();

        String collectionClassShortName = collectionClassRawName.substring(collectionClassRawName.lastIndexOf(DOT_CHR) + 1);
        String suggestedClassName = collectionClassShortName + "Of" + name;
        String qualifiedClassName = packageName + DOT_CHR + suggestedClassName;
        qualifiedClassName = getNextAvailableClassName(qualifiedClassName);

        String qualifiedInternalClassName = qualifiedClassName.replace(DOT_CHR, SLASH_CHR);

        byte[] classBytes;
        if(multiDimensional) {
            classBytes = generateMultiDimensionalManyValueClass(typeMappingInfo, namespace, MultiDimensionalCollectionValue.class, qualifiedInternalClassName, componentClass, collectionClass);
        } else {
            classBytes = generateManyValue(typeMappingInfo, namespace, CollectionValue.class, qualifiedInternalClassName, componentClass, collectionClass);
        }
        return generateClassFromBytes(qualifiedClassName, classBytes);
    }

    private java.lang.reflect.Type getNestedCollectionType(TypeMappingInfo mappingInfo) {
        java.lang.reflect.Type result = null;
        if (mappingInfo != null && mappingInfo.getType() != null) {
            // called for a collection, type must be parametrized ...
            ParameterizedType pType = (ParameterizedType) mappingInfo.getType();
            java.lang.reflect.Type[] actualTypeArguments = pType.getActualTypeArguments();
            result = actualTypeArguments != null && actualTypeArguments.length > 0 ? actualTypeArguments[0] : null;
        }
        if (result == null) {
            getLogger().logWarning("cant_get_nested_collection_type", new Object[]{});
        }
        return result;
    }

    private byte[] generateManyValue(TypeMappingInfo typeMappingInfo, String namespace, Class superType, String classNameSeparatedBySlash, JavaClass componentType, JavaClass containerType) {
        EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();
        generateManyValueClass(cw, typeMappingInfo, namespace, superType, classNameSeparatedBySlash, componentType, containerType);
        cw.visitEnd();
        return cw.toByteArray();
    }

    private void generateManyValueClass(EclipseLinkASMClassWriter cw, TypeMappingInfo typeMappingInfo, String namespace, Class superType, String classNameSeparatedBySlash, JavaClass componentType, JavaClass containerType) {
        String componentClassNameSeparatedBySlash = getObjectType(componentType).getQualifiedName().replace(DOT_CHR, SLASH_CHR);
        String containerClassNameSeperatedBySlash = containerType.getQualifiedName().replace(DOT_CHR, SLASH_CHR);
        if("[B".equals(componentClassNameSeparatedBySlash)) {
            cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classNameSeparatedBySlash, "L" + Type.getInternalName(superType) + "<" + componentClassNameSeparatedBySlash + ">;", Type.getInternalName(superType), null);
        } else {
            cw.visit(Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, classNameSeparatedBySlash, "L" + Type.getInternalName(superType) + "<L" + componentClassNameSeparatedBySlash + ";>;", Type.getInternalName(superType), null);
        }

        // Write @XmlType(namespace)
        AnnotationVisitor av = cw.visitAnnotation("Ljakarta/xml/bind/annotation/XmlType;", true);
        if(null != namespace) {
            av.visit("namespace", namespace);
        }
        if(classNameSeparatedBySlash.startsWith(ARRAY_PACKAGE_NAME.replace('.', '/')) && classNameSeparatedBySlash.contains("QName") ) {
            av.visit("name", classNameSeparatedBySlash.substring(classNameSeparatedBySlash.lastIndexOf('/') + 1));
        }
        av.visitEnd();

        // Public No-Arg Constructor
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "<init>", "()V", null, null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(superType), "<init>", "()V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        if(!componentType.isPrimitive() &&  ArrayValue.class.isAssignableFrom(superType)){

            //@Override
            //public Object getItem() {
            //    if(null == adaptedValue) {
            //        return null;
            //    }
            //    int len = adaptedValue.size();
            //    Float[] array = new Float[len];
            //    adaptedValue.toArray(array);
            //    return array;
            // }
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getItem", "()Ljava/lang/Object;", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, classNameSeparatedBySlash, "adaptedValue", "Ljava/util/Collection;");
            Label l0 = new Label();
            mv.visitJumpInsn(Opcodes.IFNONNULL, l0);
            mv.visitInsn(Opcodes.ACONST_NULL);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitLabel(l0);
            mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, classNameSeparatedBySlash, "adaptedValue", "Ljava/util/Collection;");
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Collection", "size", "()I", true);
            mv.visitVarInsn(Opcodes.ISTORE, 1);
            mv.visitVarInsn(Opcodes.ILOAD, 1);
            mv.visitTypeInsn(Opcodes.ANEWARRAY, componentClassNameSeparatedBySlash);
            mv.visitVarInsn(Opcodes.ASTORE, 2);
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitFieldInsn(Opcodes.GETFIELD, classNameSeparatedBySlash, "adaptedValue", "Ljava/util/Collection;");
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, "java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", true);
            mv.visitInsn(Opcodes.POP);

            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitInsn(Opcodes.ARETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();


            //@Override
            //public void setItem(Object array) {
            //    Float[] floatArray = (Float[])array;
            //    adaptedValue =   (Collection<T>) Arrays.asList(floatArray);
            //}
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setItem", "(Ljava/lang/Object;)V", null, null);
            mv.visitCode();
            mv.visitVarInsn(Opcodes.ALOAD, 1);
            mv.visitTypeInsn(Opcodes.CHECKCAST, "[L"+componentClassNameSeparatedBySlash+";");
            mv.visitVarInsn(Opcodes.ASTORE, 2);
            mv.visitVarInsn(Opcodes.ALOAD, 0);
            mv.visitVarInsn(Opcodes.ALOAD, 2);
            mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/util/Arrays", "asList", "([Ljava/lang/Object;)Ljava/util/List;", false);
            mv.visitFieldInsn(Opcodes.PUTFIELD, classNameSeparatedBySlash, "adaptedValue", "Ljava/util/Collection;");
            mv.visitInsn(Opcodes.RETURN);
            mv.visitMaxs(2, 3);
            mv.visitEnd();
        }


        // @XmlElement(name="item", nillable=true)
        // public Collection<COMPONENT_TYPE> getAdaptedValue() {
        //    return super.getAdaptedValue();
        // }
        // OR
        // @XmlValue
        // public Collection<COMPONENT_TYPE> getAdaptedValue() {
        //    return super.getAdaptedValue();
        // }
        if("[B".equals(componentClassNameSeparatedBySlash)) {
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getAdaptedValue", "()Ljava/util/Collection;", "()Ljava/util/Collection<" + componentClassNameSeparatedBySlash + ">;", null);
        } else {
            mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "getAdaptedValue", "()Ljava/util/Collection;", "()Ljava/util/Collection<L" + componentClassNameSeparatedBySlash + ";>;", null);
        }
        // Copy annotations
        boolean hasXmlList = false;
        Annotation[] annotations;
        if (typeMappingInfo != null && ((annotations = getAnnotations(typeMappingInfo)) != null)) {
            for (Annotation annotation : annotations) {
                if(!(annotation instanceof XmlElement || annotation instanceof XmlJavaTypeAdapter)) {
                    Class<? extends Annotation> annotationType = annotation.annotationType();
                    //if(annotationType.equals(XmlList.class)) {
                    if(annotation instanceof XmlList) {
                        hasXmlList = true;
                    }
                    av = mv.visitAnnotation(L + annotationType.getName().replace(DOT_CHR, SLASH_CHR) + SEMI_COLON, true);
                    for (Method next : annotation.annotationType().getDeclaredMethods()) {
                        try {
                            Object nextValue = next.invoke(annotation, new Object[] {});
                            if (nextValue instanceof Class) {
                                nextValue = Type.getType(L + ((Class) nextValue).getName().replace(DOT_CHR, SLASH_CHR) + SEMI_COLON);
                            }
                            av.visit(next.getName(), nextValue);
                        } catch (InvocationTargetException ex) {
                        } catch (IllegalAccessException ex) {
                        }
                    }
                    av.visitEnd();
                }
            }
        }
        if(hasXmlList) {
            // @XmlValue
            av = mv.visitAnnotation("Ljakarta/xml/bind/annotation/XmlValue;", true);
            av = mv.visitAnnotation("Lorg/eclipse/persistence/oxm/annotations/XmlValueExtension;", true);
            av.visitEnd();
        } else {
            // @XmlElement(name="item", nillable=true)
            av = mv.visitAnnotation("Ljakarta/xml/bind/annotation/XmlElement;", true);
            av.visit("name", ITEM);
            av.visit("nillable", true);
            av.visitEnd();
        }

        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(superType), "getAdaptedValue", "()Ljava/util/Collection;", false);
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();

        // public void setAdaptedValue(Collection<COMPONENT_TYPE> adaptedValue) {
        //     super.setAdaptedValue(adaptedValue);
        // }
        mv = cw.visitMethod(Opcodes.ACC_PUBLIC, "setAdaptedValue", "(Ljava/util/Collection;)V", "(Ljava/util/Collection<L" + componentClassNameSeparatedBySlash + ";>;)V", null);
        mv.visitCode();
        mv.visitVarInsn(Opcodes.ALOAD, 0);
        mv.visitVarInsn(Opcodes.ALOAD, 1);
        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, Type.getInternalName(superType), "setAdaptedValue", "(Ljava/util/Collection;)V", false);
        mv.visitInsn(Opcodes.RETURN);
        mv.visitMaxs(2, 2);
        mv.visitEnd();

        // public Class<?> containerClass() {
        //     return CONTAINER_TYPE.class;
        // }
        mv = cw.visitMethod(Opcodes.ACC_PROTECTED, "containerClass", "()Ljava/lang/Class;", "()Ljava/lang/Class<*>;", null);
        mv.visitCode();
        if(componentType.isPrimitive()) {
            mv.visitFieldInsn(Opcodes.GETSTATIC, getObjectType(componentType).getQualifiedName().replace(DOT_CHR, SLASH_CHR), "TYPE", "Ljava/lang/Class;");
        } else {
            if(containerClassNameSeperatedBySlash.contains(";")) {
                mv.visitLdcInsn(Type.getType(containerClassNameSeperatedBySlash));
            } else {
                mv.visitLdcInsn(Type.getType("L" + containerClassNameSeperatedBySlash + ";"));
            }
        }
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    private byte[] generateMultiDimensionalManyValueClass(TypeMappingInfo typeMappingInfo, String namespace, Class superType, String classNameSeparatedBySlash, JavaClass componentType, JavaClass containerType) {
        EclipseLinkASMClassWriter cw = new EclipseLinkASMClassWriter();
        generateManyValueClass(cw, typeMappingInfo, namespace, superType, classNameSeparatedBySlash, componentType, containerType);
        generateMultiDimensionalManyValueClass(cw, componentType);
        cw.visitEnd();
        return cw.toByteArray();
    }

    private void generateMultiDimensionalManyValueClass(ClassWriter cw, JavaClass componentType) {
        // public Class<?> componentClass() {
        //    return COMPONENT_TYPE.class;
        // }
        String componentClassNameSeparatedBySlash = componentType.getQualifiedName().replace(DOT_CHR, SLASH_CHR);
        MethodVisitor mv = cw.visitMethod(Opcodes.ACC_PROTECTED, "componentClass", "()Ljava/lang/Class;", "()Ljava/lang/Class<L" + componentClassNameSeparatedBySlash + ";>;", null);
        mv.visitCode();
        mv.visitLdcInsn(Type.getType("L" + componentClassNameSeparatedBySlash + ";"));
        mv.visitInsn(Opcodes.ARETURN);
        mv.visitMaxs(1, 1);
        mv.visitEnd();
    }

    private Class generateClassFromBytes(String className, byte[] classBytes) {
        JaxbClassLoader loader = (JaxbClassLoader) helper.getClassLoader();
        Class generatedClass = loader.generateClass(className, classBytes);
        return generatedClass;
    }

    /**
     * Inner class used for ordering a list of Properties alphabetically by
     * property name.
     *
     */
    private static final class PropertyComparitor implements Comparator<Property> {
        @Override
        public int compare(Property p1, Property p2) {
            return p1.getPropertyName().compareTo(p2.getPropertyName());
        }
    }

    private String getNextAvailableClassName(String suggestedName) {
        int counter = 1;
        return getNextAvailableClassName(suggestedName, suggestedName, counter);
    }

    private String getNextAvailableClassName(String suggestedBaseName, String suggestedName, int counter) {

        Iterator<Class> iter = typeMappingInfosToGeneratedClasses.values().iterator();
        while (iter.hasNext()) {
            Class nextClass = iter.next();
            if (nextClass.getName().equals(suggestedName)) {
                counter = counter + 1;
                return getNextAvailableClassName(suggestedBaseName, suggestedBaseName + counter, counter);
            }
        }
        return suggestedName;
    }

    private Class getPrimitiveClass(String primitiveClassName) {
        return ConversionManager.getDefaultManager().convertClassNameToClass(primitiveClassName);
    }

    private Class getObjectClass(Class primitiveClass) {
        return ConversionManager.getObjectClass(primitiveClass);
    }

    public Map<java.lang.reflect.Type, Class> getCollectionClassesToGeneratedClasses() {
        return collectionClassesToGeneratedClasses;
    }

    public Map<String, Class> getArrayClassesToGeneratedClasses() {
        return arrayClassesToGeneratedClasses;
    }

    public Map<Class, java.lang.reflect.Type> getGeneratedClassesToCollectionClasses() {
        return generatedClassesToCollectionClasses;
    }

    public Map<Class, JavaClass> getGeneratedClassesToArrayClasses() {
        return generatedClassesToArrayClasses;
    }

    /**
     * Convenience method for returning all of the TypeInfo objects for a given
     * package name.
     *
     * This method is inefficient as we need to iterate over the entire typeinfo
     * map for each call. We should eventually store the TypeInfos in a Map
     * based on package name, i.e.:
     *
     * Map {@literal <String, Map<String, TypeInfo>>}
     *
     * @return List of TypeInfo objects for a given package name
     */
    public Map<String, TypeInfo> getTypeInfosForPackage(String packageName) {
        Map<String, TypeInfo> typeInfos = new HashMap<String, TypeInfo>();
        List<JavaClass> jClasses = getTypeInfoClasses();
        for (JavaClass jClass : jClasses) {
            if (jClass.getPackageName().equals(packageName)) {
                String key = jClass.getQualifiedName();
                typeInfos.put(key, this.typeInfos.get(key));
            }
        }
        return typeInfos;
    }

    /**
     * Set namespace override info from XML bindings file. This will typically
     * be called from the XMLProcessor.
     *
     */
    public void setPackageToNamespaceMappings(HashMap<String, NamespaceInfo> packageToNamespaceMappings) {
        //this.packageToNamespaceMappings = packageToNamespaceMappings;
    }

    public void setPackageToPackageInfoMappings(HashMap<String, PackageInfo> packageToPackageInfoMappings) {
        this.packageToPackageInfoMappings = packageToPackageInfoMappings;
    }

    public SchemaTypeInfo addClass(JavaClass javaClass) {
        if (javaClass == null) {
            return null;
        } else if (helper.isAnnotationPresent(javaClass, XmlTransient.class)) {
            return null;
        }

        if (typeInfos == null) {
            // this is the first class. Initialize all the properties
            this.typeInfoClasses = new ArrayList<JavaClass>();
            this.typeInfos = new HashMap<String, TypeInfo>();
            this.typeQNames = new ArrayList<QName>();
            this.userDefinedSchemaTypes = new HashMap<String, QName>();
            this.packageToPackageInfoMappings = new HashMap<String, PackageInfo>();
        }

        JavaClass[] jClasses = new JavaClass[] { javaClass };
        buildNewTypeInfo(jClasses);
        TypeInfo info = typeInfos.get(javaClass.getQualifiedName());

        PackageInfo packageInfo;
        String packageName = javaClass.getPackageName();
        packageInfo = this.packageToPackageInfoMappings.get(packageName);

        SchemaTypeInfo schemaInfo = new SchemaTypeInfo();
        schemaInfo.setSchemaTypeName(new QName(info.getClassNamespace(), info.getSchemaTypeName()));

        if (info.isSetXmlRootElement()) {
            org.eclipse.persistence.jaxb.xmlmodel.XmlRootElement xmlRE = info.getXmlRootElement();
            String elementName = xmlRE.getName();
            if (elementName.equals(XMLProcessor.DEFAULT) || elementName.equals(EMPTY_STRING)) {
                try {
                    elementName = info.getXmlNameTransformer().transformRootElementName(javaClass.getName());
                } catch (Exception ex) {
                    throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringNameTransformation(javaClass.getName(), info.getXmlNameTransformer().getClass().getName(), ex);
                }
            }
            String rootNamespace = xmlRE.getNamespace();
            QName rootElemName = null;
            if (rootNamespace.equals(XMLProcessor.DEFAULT)) {
                rootElemName = new QName(packageInfo.getNamespace(), elementName);
            } else {
                rootElemName = new QName(rootNamespace, elementName);
            }
            schemaInfo.getGlobalElementDeclarations().add(rootElemName);
            ElementDeclaration declaration = new ElementDeclaration(rootElemName, javaClass, javaClass.getRawName(), false);
            addGlobalElement(rootElemName, declaration);
        }

        return schemaInfo;
    }

    /**
     * Convenience method which class pre and postBuildTypeInfo for a given set
     * of JavaClasses.
     *
     */
    public void buildNewTypeInfo(JavaClass[] javaClasses) {
        preBuildTypeInfo(javaClasses);
        javaClasses = postBuildTypeInfo(javaClasses);
        for(JavaClass next:javaClasses) {
            processPropertyTypes(next);
        }
    }

    /**
     * Pre-process a descriptor customizer. Here, the given JavaClass is checked
     * for the existence of an @XmlCustomizer annotation.
     *
     * Note that the post processing of the descriptor customizers will take
     * place in MappingsGenerator's generateProject method, after the
     * descriptors and mappings have been generated.
     *
     * @see XmlCustomizer
     * @see MappingsGenerator
     */
    private void preProcessCustomizer(JavaClass jClass, TypeInfo tInfo) {
        XmlCustomizer xmlCustomizer = (XmlCustomizer) helper.getAnnotation(jClass, XmlCustomizer.class);
        if (xmlCustomizer != null) {
            tInfo.setXmlCustomizer(xmlCustomizer.value().getName());
        }
    }

    /**
     * Lazy load the metadata logger.
     *
     */
    private JAXBMetadataLogger getLogger() {
        if (logger == null) {
            logger = new JAXBMetadataLogger();
        }
        return logger;
    }

    /**
     * Return the Helper object set on this processor.
     *
     */
    Helper getHelper() {
        return this.helper;
    }

    public boolean isDefaultNamespaceAllowed() {
        return isDefaultNamespaceAllowed;
    }

    public List<ElementDeclaration> getLocalElements() {
        return this.localElements;
    }

    public Map<TypeMappingInfo, Class> getTypeMappingInfosToGeneratedClasses() {
        return this.typeMappingInfosToGeneratedClasses;
    }

    public Map<TypeMappingInfo, Class> getTypeMappingInfoToAdapterClasses() {
        return this.typeMappingInfoToAdapterClasses;
    }

    /**
     * Add an XmlRegistry to ObjectFactory class name pair to the map.
     *
     * @param factoryClassName
     * ObjectFactory class name
     * @param xmlReg
     * org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry instance
     */
    public void addXmlRegistry(String factoryClassName, org.eclipse.persistence.jaxb.xmlmodel.XmlRegistry xmlReg) {
        this.xmlRegistries.put(factoryClassName, xmlReg);
    }

    /**
     * Convenience method for determining if a given JavaClass should be
     * processed as an ObjectFactory class.
     *
     * @return true if the JavaClass is annotated with @XmlRegistry or the map
     * of XmlRegistries contains a key equal to the JavaClass' qualified
     * name
     */
    private boolean isXmlRegistry(JavaClass javaClass) {
        if (javaClass == null) {
            return false;
        }
        return (helper.isAnnotationPresent(javaClass, XmlRegistry.class) || xmlRegistries.get(javaClass.getQualifiedName()) != null);
    }

    public Map<TypeMappingInfo, QName> getTypeMappingInfosToSchemaTypes() {
        return this.typeMappingInfosToSchemaTypes;
    }

    String getDefaultTargetNamespace() {
        return this.defaultTargetNamespace;
    }

    void setDefaultTargetNamespace(String defaultTargetNamespace) {
        this.defaultTargetNamespace = defaultTargetNamespace;
    }

    public void setDefaultNamespaceAllowed(boolean isDefaultNamespaceAllowed) {
        this.isDefaultNamespaceAllowed = isDefaultNamespaceAllowed;
    }

    Map<QName, ElementDeclaration> getElementDeclarationsForScope(String scopeClassName) {
        return this.elementDeclarations.get(scopeClassName);
    }

    private void addGlobalElement(QName key, ElementDeclaration declaration){
        getGlobalElements().put(key, declaration);
        classesToProcessPropertyTypes.add(declaration.getJavaType());
    }

    private Map<Object, Object> createUserPropertiesMap(XmlProperty[] properties) {
        Map<Object, Object> propMap = new HashMap<Object, Object>();
        for (XmlProperty prop : properties) {
            Object pvalue = prop.value();
            if (!(prop.valueType() == String.class)) {
                pvalue = XMLConversionManager.getDefaultXMLManager().convertObject(prop.value(), prop.valueType());
            }
            propMap.put(prop.name(), pvalue);
        }
        return propMap;
    }

    /**
     * Indicates if a given Property represents an MTOM attachment. Will return
     * true if the given Property's actual type is one of:
     *
     * - DataHandler - byte[] - Byte[] - Image - Source - MimeMultipart
     *
     */
    public boolean isMtomAttachment(Property property) {
        JavaClass ptype = property.getActualType();
        return (areEquals(ptype, JAVAX_ACTIVATION_DATAHANDLER) || areEquals(ptype, byte[].class) || areEquals(ptype, Image.class) || areEquals(ptype, Source.class) || areEquals(ptype, JAVAX_MAIL_INTERNET_MIMEMULTIPART));
    }

    public boolean hasSwaRef() {
        return this.hasSwaRef;
    }

    public void setHasSwaRef(boolean swaRef) {
        this.hasSwaRef = swaRef;
    }

    public List getReferencedByTransformer(){
        return referencedByTransformer;
    }

    /**
     * Indicates whether this AnnotationsProcessor has been configured to enable
     * processing of XmlAccessorFactory annotations.
     *
     * @see "com.sun.xml.bind.XmlAccessorFactory"
     */
    public boolean isXmlAccessorFactorySupport() {
        return xmlAccessorFactorySupport;
    }

    /**
     * Sets whether this AnnotationsProcessor should process XmlAccessorFactory annotations.
     *
     * @see "com.sun.xml.bind.XmlAccessorFactory"
     */
    public void setXmlAccessorFactorySupport(boolean value) {
        this.xmlAccessorFactorySupport = value;
    }

    public void setHasXmlBindings(boolean b) {
        this.hasXmlBindings = true;
    }

    public boolean hasXmlBindings() {
        return this.hasXmlBindings;
    }
}
