/*
 * 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
//     Marcel Valovy - 2.6 - added ci unmarshalling & BV in JAXB
//     Dmitry Kornilov - 2.6.1 - BeanValidationHelper refactoring
package org.eclipse.persistence.jaxb;

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

import java.awt.Image;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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 java.util.StringTokenizer;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicBoolean;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.SchemaOutputResolver;
import jakarta.xml.bind.ValidationEvent;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import java.util.HashSet;
import javax.xml.namespace.QName;
import javax.xml.stream.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.transform.Source;
import org.eclipse.persistence.Version;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.core.sessions.CoreProject;
import org.eclipse.persistence.descriptors.ClassDescriptor;
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.ConversionManager;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.jaxb.JAXBSchemaOutputResolver;
import org.eclipse.persistence.internal.jaxb.JaxbClassLoader;
import org.eclipse.persistence.internal.jaxb.ObjectGraphImpl;
import org.eclipse.persistence.internal.jaxb.WrappedValue;
import org.eclipse.persistence.internal.jaxb.json.schema.JsonSchemaGenerator;
import org.eclipse.persistence.internal.jaxb.json.schema.model.JsonSchema;
import org.eclipse.persistence.internal.jaxb.many.ManyValue;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.ChoiceObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Field;
import org.eclipse.persistence.internal.oxm.schema.SchemaModelGenerator;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jaxb.compiler.Generator;
import org.eclipse.persistence.jaxb.compiler.MarshalCallback;
import org.eclipse.persistence.jaxb.compiler.UnmarshalCallback;
import org.eclipse.persistence.jaxb.javamodel.JavaClass;
import org.eclipse.persistence.jaxb.javamodel.reflection.AnnotationHelper;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaClassImpl;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelImpl;
import org.eclipse.persistence.jaxb.javamodel.reflection.JavaModelInputImpl;
import org.eclipse.persistence.jaxb.json.JsonSchemaOutputResolver;
import org.eclipse.persistence.jaxb.xmlmodel.JavaType;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings;
import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.LogLevel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLContext;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.XMLLogin;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.platform.SAXPlatform;
import org.eclipse.persistence.oxm.platform.XMLPlatform;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.SessionEventListener;

/**
 * <p><b>Purpose:</b>Provide a EclipseLink implementation of the JAXBContext interface.</p>
 * <p><b>Responsibilities:</b><ul>
 * <li>Create Marshaller instances</li>
 * <li>Create Unmarshaller instances</li>
 * <li>Create Binder instances</li>
 * <li>Create Introspector instances</li>
 * <li>Create Validator instances</li>
 * <li>Generate Schema Files</li>
 * </ul>
 * <p>This is the EclipseLink JAXB 2.0 implementation of jakarta.xml.bind.JAXBContext. This class
 * is created by the JAXBContextFactory and is used to create Marshallers, Unmarshallers, Validators,
 * Binders and Introspectors. A JAXBContext can also be used to create Schema Files.</p>
 * <p><b>Bootstrapping:</b>
 * When bootstrapping the JAXBContext from a EclipseLink externalized metadata file(s) a number of
 * input options are available.  The externalized metadata file (one per package) is passed in
 * through a property when creating the JAXBContext.  The key used in the properties map is
 * "eclipselink-oxm-xml".  The externalized metadata file can be set in the properties map in
 * one of three ways:</p>
 * <p>i) For a single externalized metadata file, one of the following can be set in the properties map:</p><ul>
 * <li>java.io.File</li>
 * <li>java.io.InputStream</li>
 * <li>java.io.Reader</li>
 * <li>java.net.URL</li>
 * <li>javax.xml.stream.XMLEventReader</li>
 * <li>javax.xml.stream.XMLStreamReader</li>
 * <li>javax.xml.transform.Source</li>
 * <li>org.w3c.dom.Node</li>
 * <li>org.xml.sax.InputSource</li></ul>
 * When using one of the above options, the package name must be set via package-name attribute on the
 * xml-bindings element in the externalized metadata file.
 * <p>ii) For multiple externalized metadata files where the package name is specified within each externalized
 * metadata file, a List can be used.  The entries in the List are to be one of the types listed in i) above.
 * </p><p>iii) For multiple externalized metadata files where the package name is not specified in each externalized
 * metadata file, a Map can be used.  The key must be a String (package name) and  each value in the Map
 * (externalized metadata file) is to be one of the types listed in i) above.
 * </p><p>Note that in each of the above cases the package name can be set via package-name attribute on the
 * xml-bindings element in the externalized metadata file.  If set, any java-type names in the given metadata
 * file that do not contain the package name will have that package name prepended to it.  Also note that a
 * List or Map can be used for a single externalized metadata file.
 * </p>
 * @see jakarta.xml.bind.JAXBContext
 * @see org.eclipse.persistence.jaxb.JAXBMarshaller
 * @see org.eclipse.persistence.jaxb.JAXBUnmarshaller
 * @see org.eclipse.persistence.jaxb.JAXBBinder
 * @see org.eclipse.persistence.jaxb.JAXBIntrospector
 * @see org.eclipse.persistence.jaxb.JAXBContextProperties
 *
 * @author mmacivor
 */

public class JAXBContext extends jakarta.xml.bind.JAXBContext {

    private static final Map<String, Boolean> PARSER_FEATURES = new HashMap<>(2);
    static {
        PARSER_FEATURES.put("http://apache.org/xml/features/validation/schema/normalized-value", false);
        PARSER_FEATURES.put("http://apache.org/xml/features/validation/schema/element-default", false);
        if (MOXySystemProperties.moxyLoggingLevel != null) {
            AbstractSessionLog.getLog().setLevel(LogLevel.toValue(MOXySystemProperties.moxyLoggingLevel).getId(), SessionLog.MOXY);
        }
    }

    private static final String RI_XML_ACCESSOR_FACTORY_SUPPORT = "org.glassfish.jaxb.XmlAccessorFactory";

    /**
      * For JAXB 2 there is no explicitly defined default validation handler
      * and the default event handling only terminates the  operation after
      * encountering a fatal error.
      */
    protected static final ValidationEventHandler DEFAULT_VALIDATION_EVENT_HANDLER = new ValidationEventHandler() {
        @Override
        public boolean handleEvent(ValidationEvent event) {
            return event.getSeverity() < ValidationEvent.FATAL_ERROR;
        }
    };

    private final AtomicBoolean hasLoggedValidatorInfo = new AtomicBoolean();
    protected JAXBContextInput contextInput;

    protected volatile JAXBContextState contextState;
    private XMLInputFactory xmlInputFactory;

    private boolean initializedXMLInputFactory = false;
    private JAXBMarshaller jsonSchemaMarshaller;

    private static volatile BeanValidationHelper beanValidationHelper;
    private static volatile Boolean beanValidationPresent;

    protected JAXBContext() {
        super();
        contextState = new JAXBContextState();
        initBeanValidation();
    }

    protected JAXBContext(JAXBContextInput contextInput) throws jakarta.xml.bind.JAXBException {
        this.contextInput = contextInput;
        this.contextState = contextInput.createContextState();
        initBeanValidation();
    }

    /**
     * Create a JAXBContext for a given XMLContext.  The XMLContext contains the
     * metadata about the Object to XML mappings.
     */
    public JAXBContext(XMLContext context) {
        contextState = new JAXBContextState(context);
        initBeanValidation();
    }

    /**
     * Create a JAXBContext. The XMLContext contains the metadata about the
     * Object to XML mappings.
     */
    public JAXBContext(XMLContext context, Generator generator, Type[] boundTypes) {
        contextState = new JAXBContextState(context, generator, boundTypes, null);
        initBeanValidation();
    }

    /**
     * Create a JAXBContext.  The XMLContext contains the metadata about the
     * Object to XML mappings.
     */
    public JAXBContext(XMLContext context, Generator generator, TypeMappingInfo[] boundTypes) {
        contextState = new JAXBContextState(context, generator, boundTypes, null);
        initBeanValidation();
    }

    /**
     * Initializes bean validation if jakarta.validation.api bundle is on the class path.
     */
    private void initBeanValidation() {
        if (beanValidationPresent == null) {
            beanValidationPresent = BeanValidationChecker.isBeanValidationPresent();
        }
        if (beanValidationPresent && beanValidationHelper == null) {
            synchronized (JAXBContext.class) {
                if (beanValidationHelper == null) {
                    // Bean validation is optional
                    beanValidationHelper = new BeanValidationHelper();
                }
            }
        }
    }

    /**
     * Returns BeanValidationHelper. Can return null if bean validation jar is not on class path.
     */
    public BeanValidationHelper getBeanValidationHelper() {
        return beanValidationHelper;
    }

    public XMLInputFactory getXMLInputFactory() {
        if (!initializedXMLInputFactory) {
            try {
                xmlInputFactory = XMLInputFactory.newInstance();
            } catch (FactoryConfigurationError e) {
            } finally {
                initializedXMLInputFactory = true;
            }
        }
        return xmlInputFactory;
    }

    AtomicBoolean getHasLoggedValidatorInfo() {
        return hasLoggedValidatorInfo;
    }

    /**
     * This event is called when context creation is completed,
     * and provides a chance to deference anything that is no longer
     * needed (to reduce the memory footprint of this object).
     */
    void postInitialize() {
        if (this.contextState.generator != null) {
            this.contextState.generator.postInitialize();
        }
    }

    /**
     * ADVANCED:
     * <p>Refresh the underlying metadata based on the inputs that were
     * used to create the JAXBContext.  This is particularly useful when using
     * the virtual property mappings.  The refreshMetadata call could be made
     * in the following way:</p>
     * <pre>org.eclipse.persistence.jaxb.JAXBHelper.getJAXBContext(aJAXBContext).refreshMetadata();</pre>
     * <b>Note:</b>
     * <ul>
     * <li>As instances of Binder maintain a cache, calling refreshMetadata will
     * not affect instances of Binder.  To get the new metadata you must create
     * a new instance of Binder after the refresh metadata call has been made.</li>
     * </ul>
     * @throws jakarta.xml.bind.JAXBException
     */
    public void refreshMetadata() throws jakarta.xml.bind.JAXBException {
        JAXBContextState newState = newContextState();
        if (newState != null) {
            contextState = newState;
        }
    }

    /**
     * INTERNAL:
     * Build a new JAXBContextState from the current JAXBContextInput.
     */
    private JAXBContextState newContextState() throws jakarta.xml.bind.JAXBException {
        if (null == contextInput) {
            return null;
        }
        synchronized (this) {
            JAXBContextState newState = contextInput.createContextState();
            XMLContext xmlContext = getXMLContext();
            xmlContext.setXMLContextState(newState.getXMLContext().getXMLContextState());
            newState.setXMLContext(xmlContext);
            newState.setTypeToTypeMappingInfo(contextState.getTypeToTypeMappingInfo());

            return newState;
        }
    }

    /**
     * INTERNAL:
     * Indicates if this JAXBContext can have its metadata refreshed.
     */
    boolean isRefreshable() {
        return false;
        /*
        if (this.contextInput.properties == null) {
            return true;
        }
        if (this.contextInput.properties.containsKey(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY)) {
            return false;
        }
        return true;
        */
    }

    /**
     * Return the XMLContext associated with this JAXBContext.
     */
    public XMLContext getXMLContext() {
        return contextState.getXMLContext();
    }

    public void setXMLContext(XMLContext xmlContext) {
        contextState.setXMLContext(xmlContext);
    }

    /**
     * Generate a Schema for this JAXBContext
     *
     * @param outputResolver Class that decides where the schema file (of the given namespace URI) will be written
     */
    @Override
    public void generateSchema(SchemaOutputResolver outputResolver)  {
        if(outputResolver instanceof JsonSchemaOutputResolver) {
            generateJsonSchema(outputResolver, ((JsonSchemaOutputResolver)outputResolver).getRootClass());
        } else {
            generateSchema(outputResolver, null);
        }
    }

    public void generateJsonSchema(SchemaOutputResolver outputResolver, Class rootClass) {
        JsonSchemaGenerator generator = new JsonSchemaGenerator(this, this.contextState.properties);
        JsonSchema schema = generator.generateSchema(rootClass);
        try {
            Marshaller m = getJsonSchemaMarshaller();
            m.marshal(schema, outputResolver.createOutput(null, rootClass.getName() + ".json"));
        } catch (Exception ex) {
            throw org.eclipse.persistence.exceptions.JAXBException.exceptionDuringSchemaGeneration(ex);
        }
    }

    private Marshaller getJsonSchemaMarshaller() throws jakarta.xml.bind.JAXBException {
        if (this.jsonSchemaMarshaller == null) {
            JAXBContext ctx = (JAXBContext) JAXBContextFactory.createContext(new Class[] { JsonSchema.class }, null);
            this.jsonSchemaMarshaller = ctx.createMarshaller();
            this.jsonSchemaMarshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
            this.jsonSchemaMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            this.jsonSchemaMarshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true);
        }

        return this.jsonSchemaMarshaller;

    }

    /**
     * Generate a Schema for this JAXBContext
     *
     * @param outputResolver Class that decides where the schema file (of the given namespace URI) will be written
     * @param additonalGlobalElements Map of additional global elements to be added to the generated XSD.
     * Note that if any QName in this map conflicts with another global element (for example from a TypeMappingInfo object)
     * then the element generated from this map will be the one that is present in the XSD.
     */
    public void generateSchema(SchemaOutputResolver outputResolver, Map<QName, Type> additonalGlobalElements) {
        JAXBContextState currentJAXBContextState = contextState;
        if (isRefreshable()) {
            // Recreate context state, to rebuild Generator
            try {
                currentJAXBContextState = newContextState();
            } catch (Exception e) {
                throw JAXBException.exceptionDuringSchemaGeneration(e);
            }
        }
        XMLContext xmlContext = currentJAXBContextState.getXMLContext();
        Generator generator = currentJAXBContextState.getGenerator();
        if (generator == null) {
            SchemaModelGenerator smGen = new SchemaModelGenerator(xmlContext.getOxmConversionManager());
            smGen.generateSchemas(xmlContext.getDescriptors(), null, new JAXBSchemaOutputResolver(outputResolver), additonalGlobalElements);
        } else {
            generator.generateSchemaFiles(outputResolver, additonalGlobalElements);
        }
    }

    /**
     * Create a JAXBMarshaller.  The JAXBMarshaller is used to convert Java objects
     * to XML.
     */
    @Override
    public JAXBMarshaller createMarshaller() throws jakarta.xml.bind.JAXBException {
        return contextState.createMarshaller(this);
    }

    /**
     * Create a JAXBUnmarshaller.  The JAXBUnmarshaller is used to convert XML into
     * Java objects.
     */
    @Override
    public JAXBUnmarshaller createUnmarshaller() throws jakarta.xml.bind.JAXBException {
        return contextState.createUnmarshaller(this);
    }

    /**
     * Create a JAXBValidator.  The JAXBValidator is used to validate Java objects against
     * an XSD.
     */
    public JAXBValidator createValidator() {
        return new JAXBValidator(getXMLContext().createValidator());
    }

    /**
     * Create a JAXBBinder.  The JAXBBinder is used to preserve unmapped XML Data.
     */
    @Override
    public JAXBBinder createBinder() {
        return contextState.createBinder(this);
    }

    /**
     * Create a JAXBBinder.  The JAXBBinder is used to preserve unmapped XML Data.
     *
     * @param nodeClass The DOM Node class to use
     */
    @Override
    public <T> JAXBBinder createBinder(Class<T> nodeClass) {
        if (nodeClass.getName().equals("org.w3c.dom.Node")) {
            return contextState.createBinder(this);
        } else {
            throw new UnsupportedOperationException(JAXBException.unsupportedNodeClass(nodeClass.getName()));
        }
    }

    /**
     * Creates a JAXBIntrospector object.  The JAXBIntrospector allows the user to
     * access certain pieces of metadata about an instance of a JAXB bound class.
     */
    @Override
    public JAXBIntrospector createJAXBIntrospector() {
        return new JAXBIntrospector(getXMLContext());
    }

    /**
     * INTERNAL:
     * Set the map containing which QName corresponds to which generated class.
     */
    public void setQNameToGeneratedClasses(HashMap<QName, Class> qNameToClass) {
        contextState.setQNameToGeneratedClasses(qNameToClass);
    }

    /**
     * INTERNAL:
     * Get the map containing which Class (by name) corresponds to which generated class.
     */
    public Map<String, Class> getClassToGeneratedClasses() {
        return contextState.getClassToGeneratedClasses();
    }

    /**
     * INTERNAL:
     * Set the map containing which Class (by name) corresponds to which generated class.
     */
    public void setClassToGeneratedClasses(HashMap<String, Class> classToClass) {
        contextState.setClassToGeneratedClasses(classToClass);
    }

    /**
     * ADVANCED:
     * Adjust the OXM metadata to take into account ORM mapping metadata
     */
    public void applyORMMetadata(AbstractSession ormSession) {
        getXMLContext().applyORMMetadata(ormSession);
    }

    /**
     * INTERNAL:
     * Get the map of which QName corresponds to which declared class.
     */
    public Map<QName, Class> getQNamesToDeclaredClasses() {
        return contextState.getQNamesToDeclaredClasses();
    }

    /**
     * INTERNAL:
     * Get the map of which QName corresponds to which generated class.
     */
    Map<QName, Class> getQNameToGeneratedClasses() {
        return contextState.getQNameToGeneratedClasses();
    }

    /**
     *  INTERNAL:
     *  Set the map of which QName corresponds to which declared class.
     */
    public void setQNamesToDeclaredClasses(HashMap<QName, Class> nameToDeclaredClasses) {
        contextState.setQNamesToDeclaredClasses(nameToDeclaredClasses);
    }

    /**
     * INTERNAL:
     * Get the map for which array class (by name) corresponds to which generated class
     */
    public Map<String, Class> getArrayClassesToGeneratedClasses() {
        if (contextState.getGenerator() == null) {
            return null;
        }
        return contextState.getGenerator().getAnnotationsProcessor().getArrayClassesToGeneratedClasses();
    }

    /**
     * INTERNAL:
     * Get the map for which collection class (by Type) corresponds to which generated class
     */
    public Map<Type, Class> getCollectionClassesToGeneratedClasses() {
        if (contextState.getGenerator() == null) {
            return null;
        }
        return contextState.getGenerator().getAnnotationsProcessor().getCollectionClassesToGeneratedClasses();
    }

    /**
     * INTERNAL:
     * Populate the map of which Type corresponds to which QName.
     * The keys should be all the boundTypes used to create the JAXBContext.
     * If the JAXBContext was not created with the constructor that takes a Type[] then
     * this Map will be empty.
     */
    public void initTypeToSchemaType() {
        contextState.initTypeToSchemaType();
    }

    /**
     * INTERNAL:
     * Get the map of which TypeMappingInfo corresponds to which QName.
     * The keys should be all the boundTypes used to create the JAXBContext.
     * If the JAXBContext was not created with the constructor that takes a TypeMappingInfo[]
     * this Map will be empty.
     */
    public Map<TypeMappingInfo, QName> getTypeMappingInfoToSchemaType() {
        return contextState.getTypeMappingInfoToSchemaType();
    }

    /**
     * INTERNAL:
     * Get the map of which Type corresponds to which QName.
     * The keys should be all the boundTypes used to create the JAXBContext.
     * If the JAXBContext was not created with the constructor that takes a Type[] then
     * this Map will be empty.
     */
    public Map<java.lang.reflect.Type, QName> getTypeToSchemaType() {
        return contextState.getTypeToSchemaType();
    }

    Map<TypeMappingInfo, Class> getTypeMappingInfoToGeneratedType() {
        return contextState.getTypeMappingInfoToGeneratedType();
    }

    Map<Type, TypeMappingInfo> getTypeToTypeMappingInfo() {
        return contextState.getTypeToTypeMappingInfo();
    }

    void setTypeToTypeMappingInfo(Map<Type, TypeMappingInfo> typeToMappingInfo) {
        contextState.setTypeToTypeMappingInfo(typeToMappingInfo);
    }

    void setTypeMappingInfoToJavaTypeAdapaters(Map<TypeMappingInfo, JAXBContext.RootLevelXmlAdapter> typeMappingInfoToAdapters) {
        contextState.setTypeMappingInfoToJavaTypeAdapaters(typeMappingInfoToAdapters);
    }

    static class RootLevelXmlAdapter {
        private XmlAdapter xmlAdapter;
        private Class boundType;

        public RootLevelXmlAdapter(XmlAdapter adapter, Class boundType) {
            this.xmlAdapter = adapter;
            this.boundType = boundType;
        }

        public XmlAdapter getXmlAdapter() {
            return xmlAdapter;
        }

        public Class getBoundType() {
            return boundType;
        }

        public void setXmlAdapter(XmlAdapter xmlAdapter) {
            this.xmlAdapter = xmlAdapter;
        }

        public void setBoundType(Class boundType) {
            this.boundType = boundType;
        }
    }

    Map<TypeMappingInfo, RootLevelXmlAdapter> getTypeMappingInfoToJavaTypeAdapters() {
        return contextState.getTypeMappingInfoToJavaTypeAdapters();
    }

    /**
     * Get a value from an object based on an XPath statement.
     *
     * @param <T>
     *      The return type of this method corresponds to the returnType parameter.
     * @param object
     *      The XPath will be executed relative to this object.
     * @param xPath
     *      The XPath statement.
     * @param namespaceResolver
     *      A <code>NamespaceResolver</code> containing the prefix/URI pairings from the XPath statement.
     * @param returnType
     *      The return type.
     *
     * @return
     *      The object corresponding to the XPath or null if no result was found.
     */
    public <T> T getValueByXPath(Object object, String xPath, NamespaceResolver namespaceResolver, Class<T> returnType) {
        return getXMLContext().getValueByXPath(object, xPath, namespaceResolver, returnType);
    }

    /**
     * Set a value on an object based on an XPath statement.
     *
     * @param object
     *      The XPath will be executed relative to this object.
     * @param xPath
     *      The XPath statement.
     * @param namespaceResolver
     *      A <code>NamespaceResolver</code> containing the prefix/URI pairings from the XPath statement.
     * @param value
     *      The value to be set.
     */
    public void setValueByXPath(Object object, String xPath, NamespaceResolver namespaceResolver, Object value) {
        getXMLContext().setValueByXPath(object, xPath, namespaceResolver, value);
    }

    /**
     * Create a new object instance for a given XML namespace and name.
     *
     * @param namespace
     *      The namespace of the complex type to create a new Java instance of.
     * @param typeName
     *      The XML type name to create a new Java instance of.
     * @param isGlobalType
     *      True if the object to be created represents a global type, false if it
     *      represents a global element.
     *
     * @return
     *      An instance of the Java class mapped to the indicated XML type, or null
     *      if no result was found.
     */
    public Object createByQualifiedName(String namespace, String typeName, boolean isGlobalType) {
        return getXMLContext().createByQualifiedName(namespace, typeName, isGlobalType);
    }

    /**
     * Create a new object instance for a given XPath, relative to the parentObject.
     *
     * @param <T>
     *      The return type of this method corresponds to the returnType parameter.
     * @param parentObject
     *      The XPath will be executed relative to this object.
     * @param xPath
     *      The XPath statement.
     * @param namespaceResolver
     *      A NamespaceResolver containing the prefix/URI pairings from the XPath statement.
     * @param returnType
     *      The return type.
     *
     * @return
     *      An instance of the Java class mapped to the supplied XML type, or null
     *      if no result was found.
     */
    public <T> T createByXPath(Object parentObject, String xPath, NamespaceResolver namespaceResolver, Class<T> returnType) {
        return getXMLContext().createByXPath(parentObject, xPath, namespaceResolver, returnType);
    }

    public ObjectGraph createObjectGraph(Class type) {
        CoreAttributeGroup group = new CoreAttributeGroup(null, type, true);
        return new ObjectGraphImpl(group);
    }

    public ObjectGraph createObjectGraph(String typeName) {
        ClassLoader loader = this.contextInput.classLoader;
        try {
            Class<Object> cls = PrivilegedAccessHelper.getClassForName(typeName, true, loader);
            return createObjectGraph(cls);
        } catch (Exception ex) {
            throw ConversionException.couldNotBeConvertedToClass(typeName, Class.class, ex);
        }
    }

    protected JAXBElement createJAXBElementFromXMLRoot(Root xmlRoot, Class declaredType) {
        Object value = xmlRoot.getObject();

        if (value instanceof List) {
            List theList = (List) value;
            for (int i = 0; i < theList.size(); i++) {
                Object next = theList.get(i);
                if (next instanceof Root) {
                    theList.set(i, createJAXBElementFromXMLRoot((Root) next, declaredType));
                }
            }
        } else if (value instanceof WrappedValue) {
            QName qname = new QName(xmlRoot.getNamespaceURI(), xmlRoot.getLocalName());
            return new JAXBElement(qname, ((WrappedValue) value).getDeclaredType(), ((WrappedValue) value).getValue());
        } else if (value instanceof JAXBElement) {
            return (JAXBElement) value;
        } else if (value instanceof ManyValue) {
            value = ((ManyValue) value).getItem();
        }

        QName qname = new QName(xmlRoot.getNamespaceURI(), xmlRoot.getLocalName());

        Map<QName, Class> qNamesToDeclaredClasses = getQNamesToDeclaredClasses();
        if (qNamesToDeclaredClasses != null && qNamesToDeclaredClasses.size() > 0) {
            Class declaredClass = qNamesToDeclaredClasses.get(qname);
            if (declaredClass != null) {
                return createJAXBElement(qname, declaredClass, value);
            }
        }

        Class xmlRootDeclaredType = xmlRoot.getDeclaredType();
        if (xmlRootDeclaredType != null) {
            return createJAXBElement(qname, xmlRootDeclaredType, value);
        }
        return createJAXBElement(qname, declaredType, value);
    }

    protected JAXBElement createJAXBElement(QName qname, Class theClass, Object value) {
        if (theClass == null) {
            return new JAXBElement(qname, Object.class, value);
        }

        if (CoreClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(theClass)) {
            theClass = CoreClassConstants.XML_GREGORIAN_CALENDAR;
        } else if (CoreClassConstants.DURATION.isAssignableFrom(theClass)) {
            theClass = CoreClassConstants.DURATION;
        }

        return new JAXBElement(qname, theClass, value);
    }

    /**
     * Returns true if any Object in this context contains a property annotated with an XmlAttachmentRef
     * annotation.
     * @return
     */
    public boolean hasSwaRef() {
        return contextState.getGenerator().getAnnotationsProcessor().hasSwaRef();
    }

    /**
     * The JAXBContextInput is used to create a JAXBContextState which is responsible for accessing
     * the underlying XMLContext
     */
    public static abstract class JAXBContextInput {

        protected Map properties;
        protected ClassLoader classLoader;

        /**
         * Create a new JAXBContextInput with the specified Map of properties and ClassLoader.
         * @param properties Map of properties.
         * @param classLoader the classLoader to use.  If null then Thread.currentThread().getContextClassLoader() will be used.
         */
        public JAXBContextInput(Map properties, ClassLoader classLoader) {
            SessionLog logger = AbstractSessionLog.getLog();
            if (properties != null && logger.shouldLog(SessionLog.FINE, SessionLog.MOXY)) {
                for (Map.Entry<Object, Object> item : (Set<Map.Entry<Object, Object>>)(properties.entrySet())) {
                    if (item.getValue() == null) {
                        logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_set_jaxb_context_property", new Object[]{item.getKey(), "NULL"});
                    } else {
                        logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_set_jaxb_context_property", new Object[]{item.getKey(), item.getValue()});
                    }
                }
            }
            this.properties = properties;
            if (null == classLoader) {
                this.classLoader = Thread.currentThread().getContextClassLoader();
            } else {
                this.classLoader = classLoader;
            }
        }

        protected abstract JAXBContextState createContextState() throws jakarta.xml.bind.JAXBException;

        protected Collection<SessionEventListener> sessionEventListeners() {
            Object eventListenerFromProperties = null;
            if (this.properties != null) {
                eventListenerFromProperties = properties.get(JAXBContextProperties.SESSION_EVENT_LISTENER);
            }

            List<SessionEventListener> eventListeners = null;

            if (null == eventListenerFromProperties) {
                eventListeners = new ArrayList<>(1);
            } else {
                if (eventListenerFromProperties instanceof SessionEventListener) {
                    eventListeners = new ArrayList<>(2);
                    eventListeners.add((SessionEventListener) eventListenerFromProperties);
                } else if (eventListenerFromProperties instanceof Collection) {
                    List<SessionEventListener> listeners = (List<SessionEventListener>) eventListenerFromProperties;
                    eventListeners = new ArrayList<>(listeners.size() + 1);
                    eventListeners.addAll(listeners);
                }
            }

            // disable instantiation policy validation during descriptor initialization
            org.eclipse.persistence.internal.jaxb.SessionEventListener eventListener = new org.eclipse.persistence.internal.jaxb.SessionEventListener();
            eventListener.setShouldValidateInstantiationPolicy(false);
            eventListeners.add(eventListener);
            return eventListeners;
        }

    }

    static class ContextPathInput extends JAXBContextInput {

        private String contextPath;

        ContextPathInput(String contextPath, Map properties, ClassLoader classLoader) {
            super(properties, classLoader);
            this.contextPath = contextPath;
        }

        @Override
        protected JAXBContextState createContextState() throws jakarta.xml.bind.JAXBException {
            boolean foundMetadata = false;
            List<Class> classes = new ArrayList<>();

            // Check properties map for eclipselink-oxm.xml entries
            Map<String, XmlBindings> xmlBindingMap = JAXBContextFactory.getXmlBindingsFromProperties(properties, classLoader);
            foundMetadata = null != xmlBindingMap && !xmlBindingMap.isEmpty();
            classes = getXmlBindingsClassesFromMap(xmlBindingMap, classLoader, classes);

            StringTokenizer tokenizer = new StringTokenizer(contextPath, ":");
            while (tokenizer.hasMoreElements()) {
                String path = tokenizer.nextToken();
                try {
                    Class<?> objectFactory = classLoader.loadClass(path + ".ObjectFactory");
                    if (isJAXB2ObjectFactory(objectFactory, classLoader)) {
                        classes.add(objectFactory);
                        foundMetadata = true;
                    }
                } catch (Exception ex) {
                    // if there's no object factory, don't worry about it. Check for jaxb.index next
                }
                try {
                    // try to load package info just to be safe
                    classLoader.loadClass(path + ".package-info");
                } catch (Exception ex) {
                }
                // Next check for a jaxb.index file in case there's one available
                InputStream jaxbIndex = classLoader.getResourceAsStream(path.replace('.', '/') + "/jaxb.index");
                if (jaxbIndex != null) {
                    foundMetadata = true;
                    BufferedReader reader = new BufferedReader(new InputStreamReader(jaxbIndex));
                    try {
                        String line = reader.readLine();
                        while (line != null) {
                            String className = path + JAXBContextFactory.PKG_SEPARATOR + line.trim();
                            try {
                                classes.add(classLoader.loadClass(className));
                            } catch (Exception ex) {
                                // just ignore for now if the class isn't available.
                            }
                            line = reader.readLine();
                        }
                    } catch (Exception ex) {
                    } finally {
                        try {
                            reader.close();
                        } catch (Exception e) {
                            // ignore
                        }
                    }
                }
            }
            if (foundMetadata) {
                Class[] classArray = new Class[classes.size()];
                for (int i = 0; i < classes.size(); i++) {
                    classArray[i] = classes.get(i);
                }
                openToCore(classes);
                return createContextState(classArray, xmlBindingMap);
            }

            Exception sessionLoadingException = null;
            try {
                openToCore(classes);
                XMLContext xmlContext = new XMLContext(contextPath, classLoader);
                return new JAXBContextState(xmlContext);
            } catch (Exception exception) {
                sessionLoadingException = exception;
            }
            JAXBException jaxbException = JAXBException.noObjectFactoryOrJaxbIndexInPath(contextPath);
            if (sessionLoadingException != null) {
                jaxbException.setInternalException(sessionLoadingException);
            }
            throw new jakarta.xml.bind.JAXBException(jaxbException);
        }

        /**
         * This means of creating a JAXBContext is aimed at creating a JAXBContext
         * based on method parameters.  This method is useful when JAXB is used as
         * the binding layer for a Web Service provider.
         */
        private JAXBContextState createContextState(Class[] classesToBeBound, Map<String, XmlBindings> xmlBindings) throws jakarta.xml.bind.JAXBException {
            JaxbClassLoader loader = PrivilegedAccessHelper.shouldUsePrivilegedAccess()
                    ? AccessController.doPrivileged(new PrivilegedAction<JaxbClassLoader>() {
                        @Override
                        public JaxbClassLoader run() {
                            return new JaxbClassLoader(classLoader, classesToBeBound);
                        }
                    })
                    : new JaxbClassLoader(classLoader, classesToBeBound);
            String defaultTargetNamespace = null;
            AnnotationHelper annotationHelper = null;
            boolean enableXmlAccessorFactory = false;
            if (properties != null) {
                if ((defaultTargetNamespace = (String) properties.get(JAXBContextProperties.DEFAULT_TARGET_NAMESPACE)) == null) {
                    // try looking up the 'old' key
                    defaultTargetNamespace = (String) properties.get(JAXBContextFactory.DEFAULT_TARGET_NAMESPACE_KEY);
                }
                if ((annotationHelper = (AnnotationHelper) properties.get(JAXBContextProperties.ANNOTATION_HELPER)) == null) {
                    // try looking up the 'old' key
                    annotationHelper = (AnnotationHelper) properties.get(JAXBContextFactory.ANNOTATION_HELPER_KEY);
                }
                Boolean xmlAccessorFactorySupport = (Boolean) properties.get(JAXBContextProperties.XML_ACCESSOR_FACTORY_SUPPORT);
                Boolean xmlAccessorFactorySupportRI = (Boolean) properties.get(RI_XML_ACCESSOR_FACTORY_SUPPORT);
                if (Boolean.TRUE.equals(xmlAccessorFactorySupport) || Boolean.TRUE.equals(xmlAccessorFactorySupportRI)) {
                    enableXmlAccessorFactory = true;
                }
            }

            JavaModelImpl jModel;
            if (annotationHelper != null) {
                jModel = new JavaModelImpl(loader, annotationHelper);
            } else {
                jModel = new JavaModelImpl(loader);
            }

            // create Map of package names to metadata complete indicators
            Map<String, Boolean> metadataComplete = new HashMap<>();
            for (String packageName : xmlBindings.keySet()) {
                if (xmlBindings.get(packageName).isXmlMappingMetadataComplete()) {
                    metadataComplete.put(packageName, true);
                }
            }
            if (metadataComplete.size() > 0) {
                jModel.setMetadataCompletePackageMap(metadataComplete);
            }

            jModel.setHasXmlBindings(!xmlBindings.isEmpty());
            JavaModelInputImpl inputImpl = new JavaModelInputImpl(classesToBeBound, jModel);
            if (properties != null) enableFacetsIfPropertySetTrue(inputImpl, properties);
            try {
                Generator generator = new Generator(inputImpl, xmlBindings, loader, defaultTargetNamespace, enableXmlAccessorFactory);
                return createContextState(generator, loader, classesToBeBound, properties);
            } catch (Exception ex) {
                throw new jakarta.xml.bind.JAXBException(ex.getMessage(), ex);
            }
        }

        private JAXBContextState createContextState(Generator generator, JaxbClassLoader loader, Type[] typesToBeBound, Map properties) throws Exception {
            CoreProject proj = generator.generateProject();
            ConversionManager conversionManager = null;
            if (classLoader != null) {
                conversionManager = new ConversionManager();
                conversionManager.setLoader(loader);
            } else {
                conversionManager = ConversionManager.getDefaultManager();
            }
            proj.convertClassNamesToClasses(conversionManager.getLoader());
            // need to make sure that the java class is set properly on each
            // descriptor when using java classname - req'd for JOT api implementation
            for (Iterator<ClassDescriptor> descriptorIt = proj.getOrderedDescriptors().iterator(); descriptorIt.hasNext();) {
                ClassDescriptor descriptor = descriptorIt.next();
                if (descriptor.getJavaClass() == null) {
                    descriptor.setJavaClass(conversionManager.convertClassNameToClass(descriptor.getJavaClassName()));
                }
            }

            XMLPlatform<org.eclipse.persistence.internal.oxm.XMLUnmarshaller> platform = new SAXPlatform();
            platform.getConversionManager().setLoader(loader);
            XMLContext xmlContext = new XMLContext((Project) proj, loader, sessionEventListeners());

            ((XMLLogin) xmlContext.getSession().getDatasourceLogin()).setEqualNamespaceResolvers(true);

            return new JAXBContextState(xmlContext, generator, typesToBeBound, properties);
        }

        /**
         * Convenience method that returns an array of Classes based on a map given XmlBindings and an
         * array of existing classes. The resulting array will not contain duplicate entries.
         */
        private List<Class> getXmlBindingsClassesFromMap(Map<String, XmlBindings> xmlBindingMap, ClassLoader classLoader, List<Class> existingClasses) {
            List<Class> additionalClasses = existingClasses;
            // for each xmlBindings
            for (Entry<String, XmlBindings> entry : xmlBindingMap.entrySet()) {
                additionalClasses = getXmlBindingsClasses(entry.getValue(), classLoader, additionalClasses);
            }
            return additionalClasses;
        }

        /**
         * Convenience method that returns a list of Classes based on a given XmlBindings and an array
         * of existing classes. The resulting array will not contain duplicate entries.
         */
        private List<Class> getXmlBindingsClasses(XmlBindings xmlBindings, ClassLoader classLoader, List<Class> existingClasses) {
            List<Class> additionalClasses = existingClasses;
            JavaTypes jTypes = xmlBindings.getJavaTypes();
            if (jTypes != null) {
                for (JavaType javaType : jTypes.getJavaType()) {
                    try {
                        Class<?> jClass = classLoader.loadClass(getQualifiedJavaTypeName(javaType.getName(), xmlBindings.getPackageName()));
                        if (!additionalClasses.contains(jClass)) {
                            additionalClasses.add(jClass);
                        }
                    } catch (ClassNotFoundException e) {
                        throw org.eclipse.persistence.exceptions.JAXBException.couldNotLoadClassFromMetadata(javaType.getName());
                    }
                }
            }
            return additionalClasses;
        }

        private boolean isJAXB2ObjectFactory(Class objectFactoryClass, ClassLoader classLoader) {
            try {
                Class<Object> xmlRegistry = PrivilegedAccessHelper.getClassForName("jakarta.xml.bind.annotation.XmlRegistry", false, classLoader);
                if (objectFactoryClass.isAnnotationPresent(xmlRegistry)) {
                    return true;
                }
                return false;
            } catch (Exception ex) {
                return false;
            }
        }

    }

    static class TypeMappingInfoInput extends JAXBContextInput {

        private TypeMappingInfo[] typeMappingInfo;

        TypeMappingInfoInput(TypeMappingInfo[] typeMappingInfo, Map properties, ClassLoader classLoader) {
            super(properties, classLoader);
            this.typeMappingInfo = Arrays.copyOf(typeMappingInfo, typeMappingInfo.length);

            Arrays.sort(this.typeMappingInfo, new Comparator<TypeMappingInfo>() {
                @Override
                public int compare(TypeMappingInfo javaClass1, TypeMappingInfo javaClass2) {
                    String sourceName = getNameForType(javaClass1.getType());
                    String targetName = getNameForType(javaClass2.getType());
                    if(sourceName == null ||  targetName == null){
                        return -1;
                    }

                    return sourceName.compareTo(targetName);
                }

                private String getNameForType(Type type) {
                    if (type instanceof Class) {
                        return ((Class)type).getCanonicalName();
                    } else if (type instanceof GenericArrayType) {
                        Class genericTypeClass = (Class) ((GenericArrayType) type).getGenericComponentType();
                        return genericTypeClass.getCanonicalName();
                    } else {
                        // assume parameterized type
                        ParameterizedType pType = (ParameterizedType) type;
                        return ((Class)pType.getRawType()).getCanonicalName();
                    }
                }
            });
        }

        @Override
        protected JAXBContextState createContextState() throws jakarta.xml.bind.JAXBException {
            // Check properties map for eclipselink-oxm.xml entries
            Map<String, XmlBindings> xmlBindings = JAXBContextFactory.getXmlBindingsFromProperties(properties, classLoader);
            String defaultTargetNamespace = null;
            AnnotationHelper annotationHelper = null;
            boolean enableXmlAccessorFactory = false;
            if (properties != null) {
                if ((defaultTargetNamespace = (String) properties.get(JAXBContextProperties.DEFAULT_TARGET_NAMESPACE)) == null) {
                    // try looking up the 'old' key
                    defaultTargetNamespace = (String) properties.get(JAXBContextFactory.DEFAULT_TARGET_NAMESPACE_KEY);
                }
                if ((annotationHelper = (AnnotationHelper) properties.get(JAXBContextProperties.ANNOTATION_HELPER)) == null) {
                    // try looking up the 'old' key
                    annotationHelper = (AnnotationHelper) properties.get(JAXBContextFactory.ANNOTATION_HELPER_KEY);
                }
                Boolean xmlAccessorFactorySupport = (Boolean) properties.get(JAXBContextProperties.XML_ACCESSOR_FACTORY_SUPPORT);
                Boolean xmlAccessorFactorySupportRI = (Boolean) properties.get(RI_XML_ACCESSOR_FACTORY_SUPPORT);
                if (Boolean.TRUE.equals(xmlAccessorFactorySupport) || Boolean.TRUE.equals(xmlAccessorFactorySupportRI)) {
                    enableXmlAccessorFactory = true;
                }
            }
            TypeMappingInfo[] typesToBeBound = typeMappingInfo;

            for (Entry<String, XmlBindings> entry : xmlBindings.entrySet()) {
                typesToBeBound = getXmlBindingsClasses(entry.getValue(), classLoader, typesToBeBound);
            }

            final TypeMappingInfo[] types = typesToBeBound;

            JaxbClassLoader loader = PrivilegedAccessHelper.shouldUsePrivilegedAccess()
                    ? AccessController.doPrivileged(new PrivilegedAction<JaxbClassLoader>() {
                        @Override
                        public JaxbClassLoader run() {
                            return new JaxbClassLoader(classLoader, types);
                        }
                    })
                    : new JaxbClassLoader(classLoader, types);
            JavaModelImpl jModel;
            if (annotationHelper != null) {
                jModel = new JavaModelImpl(loader, annotationHelper);
            } else {
                jModel = new JavaModelImpl(loader);
            }

            if (xmlBindings != null) {
                jModel.setHasXmlBindings(!xmlBindings.isEmpty());
                // create Map of package names to metadata complete indicators
                Map<String, Boolean> metadataComplete = new HashMap<>();
                for (String packageName : xmlBindings.keySet()) {
                    if (xmlBindings.get(packageName).isXmlMappingMetadataComplete()) {
                        metadataComplete.put(packageName, true);
                    }
                }

                if (metadataComplete.size() > 0) {
                    jModel.setMetadataCompletePackageMap(metadataComplete);
                }
            }

            JavaModelInputImpl inputImpl = new JavaModelInputImpl(typesToBeBound, jModel);
            if (properties != null) enableFacetsIfPropertySetTrue(inputImpl, properties);
            try {
                openToCore(inputImpl);
                Generator generator = new Generator(inputImpl, typesToBeBound, inputImpl.getJavaClasses(), null, xmlBindings, classLoader, defaultTargetNamespace, enableXmlAccessorFactory);
                JAXBContextState contextState = createContextState(generator, loader, typesToBeBound, properties);
                return contextState;
            } catch (Exception ex) {
                throw new jakarta.xml.bind.JAXBException(ex.getMessage(), ex);
            }
        }

        private JAXBContextState createContextState(Generator generator, JaxbClassLoader loader, TypeMappingInfo[] typesToBeBound, Map properties) throws Exception {
            CoreProject proj = generator.generateProject();
            ConversionManager conversionManager = null;
            if (classLoader != null) {
                conversionManager = new ConversionManager();
                conversionManager.setLoader(loader);
            } else {
                conversionManager = ConversionManager.getDefaultManager();
            }
            proj.convertClassNamesToClasses(conversionManager.getLoader());
            // need to make sure that the java class is set properly on each
            // descriptor when using java classname - req'd for JOT api implementation
            for (ClassDescriptor descriptor : (Iterable<ClassDescriptor>) proj.getOrderedDescriptors()) {
                if (descriptor.getJavaClass() == null) {
                    descriptor.setJavaClass(conversionManager.convertClassNameToClass(descriptor.getJavaClassName()));
                }
            }

            XMLPlatform<org.eclipse.persistence.internal.oxm.XMLUnmarshaller> platform = new SAXPlatform();
            platform.getConversionManager().setLoader(loader);
            XMLContext xmlContext = new XMLContext((Project) proj, loader, sessionEventListeners());

            ((XMLLogin) xmlContext.getSession().getDatasourceLogin()).setEqualNamespaceResolvers(true);

            JAXBContextState contextState = new JAXBContextState(xmlContext, generator, typesToBeBound, properties);

            for (TypeMappingInfo typeMappingInfo : typesToBeBound) {
                Type classToLookup = typeMappingInfo.getType();
                if (contextState.getTypeMappingInfoToGeneratedType() != null && contextState.getTypeMappingInfoToGeneratedType().size() > 0) {
                    Class generatedClass = contextState.getTypeMappingInfoToGeneratedType().get(typeMappingInfo);
                    if (generatedClass != null) {
                        classToLookup = generatedClass;
                    }
                }
                if (classToLookup != null && classToLookup.getClass() == Class.class) {
                    Descriptor xmlDescriptor = (Descriptor) proj.getDescriptor((Class) classToLookup);
                    typeMappingInfo.setXmlDescriptor(xmlDescriptor);
                }
            }

            return contextState;
        }

        /**
         * Convenience method that returns an array of Types based on a given XmlBindings. The resulting
         * array will not contain duplicate entries.
         */
        private static TypeMappingInfo[] getXmlBindingsClasses(XmlBindings xmlBindings, ClassLoader classLoader, TypeMappingInfo[] existingTypes) {
            JavaTypes jTypes = xmlBindings.getJavaTypes();
            if (jTypes != null) {
                List<Class> existingClasses = new ArrayList<>(existingTypes.length);
                for (TypeMappingInfo typeMappingInfo : existingTypes) {
                    Type type = typeMappingInfo.getType();
                    if (type == null) {
                        throw org.eclipse.persistence.exceptions.JAXBException.nullTypeOnTypeMappingInfo(typeMappingInfo.getXmlTagName());
                    }
                    // ignore ParameterizedTypes
                    if (type instanceof Class) {
                        Class cls = (Class) type;
                        existingClasses.add(cls);
                    }
                }

                List<TypeMappingInfo> additionalTypeMappingInfos = new ArrayList<>(jTypes.getJavaType().size());

                for (JavaType javaType : jTypes.getJavaType()) {
                    try {
                        Class<?> nextClass = classLoader.loadClass(getQualifiedJavaTypeName(javaType.getName(), xmlBindings.getPackageName()));
                        if (!(existingClasses.contains(nextClass))) {
                            TypeMappingInfo typeMappingInfo = new TypeMappingInfo();
                            typeMappingInfo.setType(nextClass);
                            additionalTypeMappingInfos.add(typeMappingInfo);
                            existingClasses.add(nextClass);
                        }
                    } catch (ClassNotFoundException e) {
                        throw org.eclipse.persistence.exceptions.JAXBException.couldNotLoadClassFromMetadata(javaType.getName());
                    }
                }

                TypeMappingInfo[] allTypeMappingInfos = new TypeMappingInfo[existingTypes.length + additionalTypeMappingInfos.size()];
                System.arraycopy(existingTypes, 0, allTypeMappingInfos, 0, existingTypes.length);
                Object[] additionalTypes = additionalTypeMappingInfos.toArray();
                System.arraycopy(additionalTypes, 0, allTypeMappingInfos, existingTypes.length, additionalTypes.length);
                return allTypeMappingInfos;
            }
            return existingTypes;
        }
    }

    protected static class JAXBContextState {

        private XMLContext xmlContext;
        private org.eclipse.persistence.jaxb.compiler.Generator generator;
        private Map<QName, Class> qNameToGeneratedClasses;
        private Map<String, Class> classToGeneratedClasses;
        private Map<QName, Class> qNamesToDeclaredClasses;
        private Map<Type, QName> typeToSchemaType;
        private TypeMappingInfo[] boundTypes;
        private Map<TypeMappingInfo, Class> typeMappingInfoToGeneratedType;
        private Map<Type, TypeMappingInfo> typeToTypeMappingInfo;
        private Map<TypeMappingInfo, JAXBContext.RootLevelXmlAdapter> typeMappingInfoToJavaTypeAdapters;
        private Map properties;

        protected JAXBContextState() {
        }

        protected JAXBContextState(XMLContext context) {
            xmlContext = context;
            updateNamespaces();
        }

        protected JAXBContextState(XMLContext context, Generator generator, Type[] boundTypes, Map properties) {
            this(context);
            this.generator = generator;
            this.qNameToGeneratedClasses = generator.getMappingsGenerator().getQNamesToGeneratedClasses();
            this.classToGeneratedClasses = generator.getMappingsGenerator().getClassToGeneratedClasses();
            this.qNamesToDeclaredClasses = generator.getMappingsGenerator().getQNamesToDeclaredClasses();
            this.boundTypes = new TypeMappingInfo[boundTypes.length];
            for (int i = 0; i < boundTypes.length; i++) {
                TypeMappingInfo newTypeInfo = new TypeMappingInfo();
                newTypeInfo.setType(boundTypes[i]);
                this.boundTypes[i] = newTypeInfo;
            }
            if (properties != null) {
                this.properties = new HashMap(properties);
            }
        }

        protected JAXBContextState(XMLContext context, Generator generator, TypeMappingInfo[] boundTypes, Map properties) {
            this(context);
            this.generator = generator;
            this.qNameToGeneratedClasses = generator.getMappingsGenerator().getQNamesToGeneratedClasses();
            this.classToGeneratedClasses = generator.getMappingsGenerator().getClassToGeneratedClasses();
            this.qNamesToDeclaredClasses = generator.getMappingsGenerator().getQNamesToDeclaredClasses();
            this.typeMappingInfoToGeneratedType = generator.getAnnotationsProcessor().getTypeMappingInfosToGeneratedClasses();
            this.setTypeMappingInfoToJavaTypeAdapaters(createAdaptersForAdapterClasses(generator.getAnnotationsProcessor().getTypeMappingInfoToAdapterClasses()));
            this.boundTypes = boundTypes;
            if (properties != null) {
                this.properties = new HashMap(properties);
            }
        }

        private Map<TypeMappingInfo, JAXBContext.RootLevelXmlAdapter> createAdaptersForAdapterClasses(Map<TypeMappingInfo, Class> typeMappingInfoToAdapterClasses) {
            Map<TypeMappingInfo, JAXBContext.RootLevelXmlAdapter> typeMappingInfoToAdapters = new HashMap<>();
            for (Entry<TypeMappingInfo, Class> entry : typeMappingInfoToAdapterClasses.entrySet()) {
                Class adapterClass = entry.getValue();
                if (adapterClass != null) {
                    try {
                        XmlAdapter adapter = (XmlAdapter) adapterClass.getConstructor().newInstance();
                        Class boundType = getBoundTypeForXmlAdapterClass(adapterClass);
                        RootLevelXmlAdapter rootLevelXmlAdapter = new RootLevelXmlAdapter(adapter, boundType);

                        typeMappingInfoToAdapters.put(entry.getKey(), rootLevelXmlAdapter);
                    } catch (Exception ex) {
                    }
                }
            }
            return typeMappingInfoToAdapters;
        }

        private Class getBoundTypeForXmlAdapterClass(Class adapterClass) {
            Class<Object> boundType = Object.class;

            for (Method method : PrivilegedAccessHelper.getDeclaredMethods(adapterClass)) {
                if (method.getName().equals("marshal")) {
                    Class<Object> returnType = PrivilegedAccessHelper.getMethodReturnType(method);
                    if (!returnType.getName().equals(boundType.getName())) {
                        boundType = returnType;
                        break;
                    }
                }
            }
            return boundType;
        }

        private void updateNamespaces() {

            Collection<ClassDescriptor> descriptors = xmlContext.getSession().getDescriptors().values();

            for (Object descriptor : descriptors) {
                Descriptor desc = (Descriptor) descriptor;
                processXMLDescriptor(new ArrayList<>(), desc, desc.getNonNullNamespaceResolver());
            }

        }

        private void processRefClasses(List processed, Set refClasses, org.eclipse.persistence.internal.oxm.NamespaceResolver nr) {
            if (refClasses != null) {
                for (Object refClass : refClasses) {
                    Class nextClass = (Class) refClass;
                    Descriptor desc = (Descriptor) xmlContext.getSession().getProject().getDescriptor(nextClass);
                    processXMLDescriptor(processed, desc, nr);
                }
            }
        }

        private void processXMLDescriptor(List<Descriptor> processed, Descriptor desc, org.eclipse.persistence.internal.oxm.NamespaceResolver nr) {
            if (desc == null || processed.contains(desc)) {
                return;
            }
            processed.add(desc);

            Vector mappings = desc.getMappings();

            for (Object mapping : mappings) {
                DatabaseMapping nextMapping = (DatabaseMapping) mapping;
                Vector<DatabaseField> fields = nextMapping.getFields();
                updateResolverForFields(fields, nr);
                Descriptor refDesc = (Descriptor) nextMapping.getReferenceDescriptor();
                if (refDesc != null && !processed.contains(refDesc)) {
                    processXMLDescriptor(processed, refDesc, nr);
                }

                if (nextMapping instanceof ChoiceObjectMapping) {
                    Set refClasses = ((ChoiceObjectMapping) nextMapping).getClassToFieldMappings().keySet();
                    processRefClasses(processed, refClasses, nr);
                } else if (nextMapping instanceof ChoiceCollectionMapping) {
                    Set refClasses = ((ChoiceCollectionMapping) nextMapping).getClassToFieldMappings().keySet();
                    processRefClasses(processed, refClasses, nr);
                }
            }
        }

        private void updateResolverForFields(Collection fields, org.eclipse.persistence.internal.oxm.NamespaceResolver nr) {
            for (Object field1 : fields) {
                Field<XMLConversionManager, NamespaceResolver> field = (XMLField) field1;
                XPathFragment currentFragment = field.getXPathFragment();

                while (currentFragment != null) {
                    String uri = currentFragment.getNamespaceURI();
                    if (uri != null) {
                        String prefix = currentFragment.getPrefix();
                        if (prefix == null || prefix.isEmpty()) {
                            if (null == nr.getDefaultNamespaceURI()) {
                                nr.setDefaultNamespaceURI(uri);
                            }
                        } else {
                            if (null == nr.resolveNamespacePrefix(prefix)) {
                                nr.put(prefix, uri);
                            }
                        }
                    }
                    currentFragment = currentFragment.getNextFragment();
                }
            }
        }

        private Map<String, Class> getClassToGeneratedClasses() {
            return classToGeneratedClasses;
        }

        private Generator getGenerator() {
            return generator;
        }

        private XMLContext getXMLContext() {
            return this.xmlContext;
        }

        private Map<java.lang.reflect.Type, QName> getTypeToSchemaType() {
            if (typeToSchemaType == null) {
                initTypeToSchemaType();
            }
            return typeToSchemaType;
        }

        private Map<TypeMappingInfo, Class> getTypeMappingInfoToGeneratedType() {
            return this.typeMappingInfoToGeneratedType;
        }

        private Map<TypeMappingInfo, RootLevelXmlAdapter> getTypeMappingInfoToJavaTypeAdapters() {
            return this.typeMappingInfoToJavaTypeAdapters;
        }

        private Map<Type, TypeMappingInfo> getTypeToTypeMappingInfo() {
            return this.typeToTypeMappingInfo;
        }

        private Map<TypeMappingInfo, QName> getTypeMappingInfoToSchemaType() {
            if (typeToTypeMappingInfo != null && typeToTypeMappingInfo.size() > 0) {
                return new HashMap<>();
            }
            return generator.getAnnotationsProcessor().getTypeMappingInfosToSchemaTypes();
        }

        private Map<QName, Class> getQNamesToDeclaredClasses() {
            return qNamesToDeclaredClasses;
        }

        /**
         * INTERNAL:
         * Get the QName which the given Type corresponds to.
         * Valid types should be all the boundTypes used to create the JAXBContext.
         * If the JAXBContext was not created with the construction that takes a Type[] then
         * this will be return null.
         */
        private QName getSchemaTypeForTypeMappingInfo(Type type) {
            QName name = null;
            //Check for annotation overrides
            if (type instanceof Class) {
                name = generator.getAnnotationsProcessor().getUserDefinedSchemaTypes().get(((Class) type).getName());
                if (name == null) {
                    Class theClass = (Class) type;
                    //Change default for byte[] to Base64 (JAXB 2.0 default)
                    if (type == CoreClassConstants.ABYTE || type == CoreClassConstants.APBYTE || type == Image.class || type == Source.class || theClass.getCanonicalName().equals("jakarta.activation.DataHandler")) {
                        name = Constants.BASE_64_BINARY_QNAME;
                    } else if (type == CoreClassConstants.OBJECT) {
                        name = Constants.ANY_TYPE_QNAME;
                    } else if (type == CoreClassConstants.XML_GREGORIAN_CALENDAR) {
                        name = Constants.ANY_SIMPLE_TYPE_QNAME;
                    } else {
                        name = XMLConversionManager.getDefaultJavaTypes().get(type);
                    }
                }
            }
            return name;
        }

        private Map<QName, Class> getQNameToGeneratedClasses() {
            return qNameToGeneratedClasses;
        }

        private void initTypeToSchemaType() {
            this.typeToSchemaType = new HashMap<>();

            if (typeToTypeMappingInfo == null || typeToTypeMappingInfo.size() == 0) {
                return;
            }

            //Add schema types generated for mapped domain classes
            for (Object o : xmlContext.getSession().getProject().getOrderedDescriptors()) {
                Descriptor next = (Descriptor) o;
                Class javaClass = next.getJavaClass();

                if (next.getSchemaReference() != null) {
                    QName schemaType = next.getSchemaReference().getSchemaContextAsQName(next.getNamespaceResolver());
                    Type type = null;
                    if (generator != null) {

                        type = generator.getAnnotationsProcessor().getGeneratedClassesToCollectionClasses().get(javaClass);

                        if (type == null) {
                            JavaClass arrayClass = generator.getAnnotationsProcessor().getGeneratedClassesToArrayClasses().get(javaClass);
                            if (arrayClass != null) {
                                String arrayClassName = arrayClass.getName();
                                try {
                                    type = PrivilegedAccessHelper.getClassForName(arrayClassName);
                                } catch (Exception ex) {
                                }
                            }

                            if (type == null && getTypeMappingInfoToGeneratedType() != null) {
                                for (Entry<TypeMappingInfo, Class> entry : getTypeMappingInfoToGeneratedType().entrySet()) {
                                    if (entry.getValue().equals(javaClass)) {
                                        type = entry.getKey().getType();
                                        break;
                                    }
                                }
                            }
                        }
                        if (type == null) {
                            type = javaClass;
                        }

                    } else {
                        type = javaClass;
                    }
                    this.typeToSchemaType.put(type, schemaType);
                }
            }

            //Add any types that we didn't generate descriptors for (built in types)
            if (boundTypes != null) {
                for (TypeMappingInfo next : this.boundTypes) {
                    Type nextType = next.getType();
                    if (this.typeToSchemaType.get(nextType) == null) {
                        QName name = getSchemaTypeForTypeMappingInfo(nextType);
                        if (name != null) {
                            this.typeToSchemaType.put(nextType, name);
                        }
                    }
                }
            }
        }

        private void setClassToGeneratedClasses(HashMap<String, Class> classToClass) {
            this.classToGeneratedClasses = classToClass;
        }

        private void setTypeToTypeMappingInfo(Map<Type, TypeMappingInfo> typeToMappingInfo) {
            this.typeToTypeMappingInfo = typeToMappingInfo;
            if (this.generator != null) {
                this.generator.setTypeToTypeMappingInfo(typeToMappingInfo);
            }
        }

        private void setTypeMappingInfoToJavaTypeAdapaters(Map<TypeMappingInfo, JAXBContext.RootLevelXmlAdapter> typeMappingInfoToAdapters) {
            this.typeMappingInfoToJavaTypeAdapters = typeMappingInfoToAdapters;
        }

        private void setQNamesToDeclaredClasses(HashMap<QName, Class> nameToDeclaredClasses) {
            qNamesToDeclaredClasses = nameToDeclaredClasses;
        }

        private void setQNameToGeneratedClasses(Map<QName, Class> qNameToClass) {
            this.qNameToGeneratedClasses = qNameToClass;
        }

        public void setXMLContext(XMLContext xmlContext) {
            this.xmlContext = xmlContext;
        }

        public JAXBMarshaller createMarshaller(JAXBContext jaxbContext) throws jakarta.xml.bind.JAXBException {
            // create a JAXBIntrospector and set it on the marshaller
            JAXBMarshaller marshaller = new JAXBMarshaller(xmlContext.createMarshaller(), jaxbContext);
            if (generator != null && generator.hasMarshalCallbacks()) {
                // initialize each callback in the map
                ClassLoader classLoader = getXMLContext().getSession(0).getDatasourcePlatform().getConversionManager().getLoader();
                for (Object o : generator.getMarshalCallbacks().keySet()) {
                    MarshalCallback cb = (MarshalCallback) generator.getMarshalCallbacks().get(o);
                    cb.initialize(classLoader);
                }
                marshaller.setMarshalCallbacks(generator.getMarshalCallbacks());
            }
            if (properties != null) {
                setPropertyOnMarshaller(JAXBContextProperties.MEDIA_TYPE, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.NAMESPACE_PREFIX_MAPPER, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_INCLUDE_ROOT, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_VALUE_WRAPPER, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_NAMESPACE_SEPARATOR, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.OBJECT_GRAPH, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.BEAN_VALIDATION_MODE, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.BEAN_VALIDATION_FACTORY, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.BEAN_VALIDATION_GROUPS, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.BEAN_VALIDATION_NO_OPTIMISATION, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_TYPE_COMPATIBILITY, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_USE_XSD_TYPES_WITH_PREFIX, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.JSON_TYPE_ATTRIBUTE_NAME, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.MOXY_LOGGING_LEVEL, marshaller);
                setPropertyOnMarshaller(JAXBContextProperties.MOXY_LOG_PAYLOAD, marshaller);
            }

            return marshaller;
        }

        public JAXBUnmarshaller createUnmarshaller(JAXBContext jaxbContext) throws jakarta.xml.bind.JAXBException {

            JAXBUnmarshaller unmarshaller = new JAXBUnmarshaller(xmlContext.createUnmarshaller(PARSER_FEATURES), jaxbContext);
            if (generator != null && generator.hasUnmarshalCallbacks()) {
                // initialize each callback in the map
                ClassLoader classLoader = getXMLContext().getSession(0).getDatasourcePlatform().getConversionManager().getLoader();
                for (Object o : generator.getUnmarshalCallbacks().keySet()) {
                    UnmarshalCallback cb = (UnmarshalCallback) generator.getUnmarshalCallbacks().get(o);
                    cb.initialize(classLoader);
                }
                unmarshaller.setUnmarshalCallbacks(generator.getUnmarshalCallbacks());
            }
            if (properties != null) {
                setPropertyOnUnmarshaller(JAXBContextProperties.MEDIA_TYPE, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_ATTRIBUTE_PREFIX, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.NAMESPACE_PREFIX_MAPPER, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_INCLUDE_ROOT, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_VALUE_WRAPPER, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_NAMESPACE_SEPARATOR, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.OBJECT_GRAPH, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.UNMARSHALLING_CASE_INSENSITIVE, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.BEAN_VALIDATION_MODE, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.BEAN_VALIDATION_FACTORY, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.BEAN_VALIDATION_GROUPS, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.BEAN_VALIDATION_NO_OPTIMISATION, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_TYPE_COMPATIBILITY, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_USE_XSD_TYPES_WITH_PREFIX, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.JSON_TYPE_ATTRIBUTE_NAME, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.MOXY_LOGGING_LEVEL, unmarshaller);
                setPropertyOnUnmarshaller(JAXBContextProperties.MOXY_LOG_PAYLOAD, unmarshaller);
            }
            return unmarshaller;
        }

        public JAXBBinder createBinder(JAXBContext context) {
        XMLMarshaller marshaller = null;
        XMLUnmarshaller unmarshaller = null;
        try {
            marshaller = createMarshaller(context).getXMLMarshaller();
            unmarshaller = createUnmarshaller(context).getXMLUnmarshaller();
        } catch (jakarta.xml.bind.JAXBException e) {
            // log something
            marshaller = context.getXMLContext().createMarshaller();
            unmarshaller = context.getXMLContext().createUnmarshaller();
        }

        return new JAXBBinder(context, marshaller, unmarshaller);
        }

        private void setPropertyOnMarshaller(String propertyName, JAXBMarshaller marshaller) throws PropertyException {
            Object propertyValue = properties.get(propertyName);
            if (propertyValue != null) {
                marshaller.setProperty(propertyName, propertyValue);
            }
        }

        private void setPropertyOnUnmarshaller(String propertyName, JAXBUnmarshaller unmarshaller) throws PropertyException {
            Object propertyValue = properties.get(propertyName);
            if (propertyValue != null) {
                unmarshaller.setProperty(propertyName, propertyValue);
            }
        }

    }

    private static void enableFacetsIfPropertySetTrue(JavaModelInputImpl inputImpl, Map properties) {
        Object propertyValue = properties.get(JAXBContextProperties.BEAN_VALIDATION_FACETS);
        if (propertyValue != null) inputImpl.setFacets((Boolean) propertyValue);
    }

    private static void openToCore(JavaModelInputImpl input) {
        JavaClass[] javaClasses = input.getJavaClasses();
        Set<Class> classes = new HashSet<>();
        for (JavaClass jc: javaClasses) {
            classes.add(((JavaClassImpl) jc).getJavaClass());
        }
        openToCore(classes);
    }

    //we need to open what has been opened to us either directly
    //or by jakarta.xml.bind API also to core on which we depend
    //to allow reflection access to code we use from that module
    private static void openToCore(Collection<Class> classes) {
        // need to open to core IF we're not eclipselink.jar
        if (NEEDS_OPEN) {
            final Module moxyModule = JAXBContext.class.getModule();
            final Module coreModule = Version.class.getModule();
            for (Class cls : classes) {
                Class jaxbClass = cls.isArray()
                        ? cls.getComponentType() : cls;

                final Module classModule = jaxbClass.getModule();
                final String packageName = jaxbClass.getPackageName();
                //no need for unnamed and java.base types
                if (!classModule.isNamed() || classModule.getName().equals("java.base")) {
                    continue;
                }
                //propagate openness to o.e.p.core module
                if (classModule.isOpen(packageName, moxyModule) && !classModule.isOpen(packageName, coreModule)) {
                    classModule.addOpens(packageName, coreModule);
                    AbstractSessionLog.getLog().log(SessionLog.FINE, SessionLog.MOXY, "open_pkg",
                            packageName, classModule.getName(), coreModule.getName());
                }
            }
        }
    }

    private static final boolean NEEDS_OPEN = JAXBContext.class.getModule() != Version.class.getModule();

}
