/*
 * 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.
     *
     * @param classes
     */
    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.
     *
     * @param tmInfo
     * @return
     */
    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.
     *
     * @param javaClasses
     * @return
     */
    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.
     *
     * @param javaClasses
     * @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.
     *
     * @param allClasses
     * @return
     */
    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.
     *
     * @param info
     */
    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.
     *
     * @param classes
     * @return
     */
    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.
     *
     * @param javaClass
     * @param classesToProcess
     */
    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.
     *
     * @param javaClass
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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).
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     * @param packageNamespace
     */
    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.
     *
     * @param javaClass
     * @param info
     * @param packageNamespace
     */
    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.
     *
     * @param javaClass
     * @param info
     * @param packageNamespace
     */
    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
     *
     * @param info
     */
    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.
     *
     * @param javaClass
     * @param info
     * @param packageNamespace
     */
    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).
     *
     * @param info
     * @param packageNamespace
     */
    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.
     *
     * @param 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
     *
     * @param property
     * @param info
     */
    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.
     *
     * @param property
     */
    private void processXmlIDREF(Property property) {
        if (helper.isAnnotationPresent(property.getElement(), XmlIDREF.class)) {
            property.setIsXmlIdRef(true);
        }
    }

    /**
     * Process @XmlJavaTypeAdapter on a given property.
     *
     * @param property
     * @param info
     * @param javaClass
     */
    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.
     *
     * @param javaClass
     * @param info
     */
    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.
     *
     * @param javaHasAnnotations
     * @return
     */
    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.
     *
     * @param choiceProperty
     * @param info
     * @param cls
     * @param propertyType
     */
    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).
     * @param javaClass
     * @param typeInfo
     * @return
     */
    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.
     *
     * @param info
     * @param javaHasAnnotations
     * @param propertyName
     * @param ptype
     * @return
     */
    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.
     *
     * @param property
     * @param info
     * @param cls
     * @return
     */
    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).
     *
     * @param property
     */
    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.
     *
     * @param src
     * @param tgt
     * @return
     */
    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.
     *
     * @param src
     * @param tgtCanonicalName
     * @return
     */
    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.
     *
     * @param name
     * @param namespace
     * @param jClassQualifiedName
     */
    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.
     *
     * @return
     */
    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>>}
     *
     * @param packageName
     * @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.
     *
     * @param packageToNamespaceMappings
     */
    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.
     *
     * @param 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.
     *
     * @param jClass
     * @param tInfo
     * @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.
     *
     * @return
     */
    private JAXBMetadataLogger getLogger() {
        if (logger == null) {
            logger = new JAXBMetadataLogger();
        }
        return logger;
    }

    /**
     * Return the Helper object set on this processor.
     *
     * @return
     */
    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.
     *
     * @param javaClass
     * @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
     *
     * @param property
     * @return
     */
    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;
    }
}
