/*
 * 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 = (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 = (Class)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 = (Class[]) 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 = (String) 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 = (Boolean)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 = (String) 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 = (Class)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 = (Class)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 = (Class)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;
    }
}
