/*
 * 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.oxm;

import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.xml.namespace.QName;

import org.eclipse.persistence.core.mappings.CoreAttributeAccessor;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.oxm.Context;
import org.eclipse.persistence.internal.oxm.ConversionManager;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.internal.oxm.XPathQName;
import org.eclipse.persistence.internal.oxm.accessor.OrmAttributeAccessor;
import org.eclipse.persistence.internal.oxm.documentpreservation.DescriptorLevelDocumentPreservationPolicy;
import org.eclipse.persistence.internal.oxm.documentpreservation.NoDocumentPreservationPolicy;
import org.eclipse.persistence.internal.oxm.mappings.CompositeCollectionMapping;
import org.eclipse.persistence.internal.oxm.mappings.CompositeObjectMapping;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.Mapping;
import org.eclipse.persistence.internal.oxm.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetClassLoaderForClass;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.oxm.documentpreservation.DocumentPreservationPolicy;
import org.eclipse.persistence.oxm.platform.SAXPlatform;
import org.eclipse.persistence.oxm.platform.XMLPlatform;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Project;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.SessionEventListener;
import org.eclipse.persistence.sessions.SessionEventManager;
import org.eclipse.persistence.sessions.factories.SessionManager;
import org.eclipse.persistence.sessions.factories.XMLSessionConfigLoader;

/**
 * <p>
 * An XMLContext is created based on EclipseLink sessions or projects and can then
 * used to create instances of XMLMarshaller, XMLUnmarshaller and XMLValidator.
 *
 * <p>
 * There are constructors to create an XMLContext with a single EclipseLink project
 * or with a String which is a single EclipseLink session name or a ':' separated
 * list of EclipseLink session names.
 *
 * <p>
 * <em>Code Sample</em><br>
 * <code>
 *  XMLContext context = new XMLContext("mySessionName");<br>
 *  XMLMarshaller marshaller = context.createMarshaller();<br>
 *  XMLUnmarshaller unmarshaller = context.createUnmarshaller();<br>
 *  XMLValidator validator = context.createValidator();<br>
 * </code>
 *
 *  <p>The XMLContext is thread-safe.  If multiple threads accessing the same XMLContext object
 *  request an XMLMarshaller, each will receive their own instance of XMLMarshaller, so any
 *  state that the XMLMarshaller maintains will be unique to that process.  The same is true
 *  of instances of XMLUnmarshaller and XMLValidator.
 *
 *  @see org.eclipse.persistence.oxm.XMLMarshaller
 *  @see org.eclipse.persistence.oxm.XMLUnmarshaller
 *  @see org.eclipse.persistence.oxm.XMLValidator
 *
 */
public class XMLContext extends Context<AbstractSession, XMLDescriptor, XMLField, NamespaceResolver, Project, DatabaseSession, SessionEventListener> {


    XMLContext(XMLContextState xmlContextState) {
        this.contextState = xmlContextState;
    }

    /**
     * Create a new XMLContext based on the specified session name or list of
     * session names
     *
     * @param sessionNames
     *            A single session name or multiple session names separated by a :
     */
    public XMLContext(String sessionNames) {
        this(sessionNames, privilegedGetClassLoaderForClass(XMLContext.class));
    }

    /**
     * Create a new XMLContext based on the specified session name or list of
     * session names
     *
     * @param sessionNames
     *            A single session name or multiple session names separated by a :
     * @param classLoader
     *            classloader for loading sessions.xml
     */
    public XMLContext(String sessionNames, ClassLoader classLoader) {
        this(sessionNames, classLoader, null);
    }

    /**
     * Create a new XMLContext based on passed in session names and session meta
     * XML.
     *
     * @param sessionNames
     *            A single session name or multiple session names separated by
     *            a:
     * @param xmlResource
     *            path to XML file containing session meta data to initialize
     *            and load sessions.
     */
    public XMLContext(String sessionNames, String xmlResource) {
        this(sessionNames, privilegedGetClassLoaderForClass(XMLContext.class), xmlResource);
    }

    /**
     * Create a new XMLContext based on passed in session names, classloader and
     * session meta XML.
     *
     * @param sessionNames
     *            A single session name or multiple session names separated by a :
     * @param classLoader
     *            classloader for loading sessions.xml
     * @param xmlResource
     *            path to XML file containing session meta data to initialize
     *            and load sessions.
     */
    public XMLContext(String sessionNames, ClassLoader classLoader, String xmlResource) {
        contextState = new XMLContextState(this, sessionNames, classLoader, xmlResource);
    }

    /**
     * Create a new XMLContext based on the specified project
     *
     * @param project
     *            An EclipseLink project
     */
    public XMLContext(Project project) {
        this(project, Thread.currentThread().getContextClassLoader());
    }

    /**
     * Create a new XMLContext based on the specified Project and ClassLoader.
     *
     * @param project An EclipseLink project
     * @param classLoader The ClassLoader to be used
     */
    public XMLContext(Project project, ClassLoader classLoader) {
        this (project, classLoader, (Collection<SessionEventListener>) null);
    }

    /**
     * Create a new XMLContext based on the specified Project and ClassLoader.
     *
     * @param project An EclipseLink project
     * @param classLoader The ClassLoader to be used
     * @param sessionEventListener If non-null, this listener will be registered with the SessionEventManager
     * @see SessionEventListener
     * @see SessionEventManager
     */
    public XMLContext(Project project, ClassLoader classLoader, SessionEventListener sessionEventListener) {
        Collection<SessionEventListener> sessionEventListeners = new ArrayList<>(1);
        sessionEventListeners.add(sessionEventListener);
        contextState = new XMLContextState(this, project, classLoader, sessionEventListeners);
    }

    /**
     * Create a new XMLContext based on the specified Project and ClassLoader.
     *
     * @param project An EclipseLink project
     * @param classLoader The ClassLoader to be used
     * @param sessionEventListeners If non-null, these listeners will be registered with the SessionEventManager
     * @see SessionEventListener
     * @see SessionEventManager
     */
    public XMLContext(Project project, ClassLoader classLoader, Collection<SessionEventListener> sessionEventListeners) {
        contextState = new XMLContextState(this, project, classLoader, sessionEventListeners);
    }

    public XMLContext(Collection projects) {
        this(projects, Thread.currentThread().getContextClassLoader());
    }

    public XMLContext(Collection projects, ClassLoader classLoader) {
        contextState = new XMLContextState(this, projects, classLoader);
    }

    /**
     * INTERNAL:  Return the XMLContextState that represents the XMLContexts
     * stateful information.  This method is provided for the benefits of layers
     * that build on top of the core OXM layer such as MOXy's JAXB
     * implementation.
     */
    public XMLContextState getXMLContextState() {
        return (XMLContextState) contextState;
    }

    /**
     * INTERNAL: Set the stateful information for this XMLContext.  Once the new
     * state has been set, OXM operations (marshal, unmarshal, etc) will be
     * based on this new state.  This method is provided for the benefit of
     * layers that build on top of the core OXM layer such as MOXy's JAXB
     *
     */
    public void setXMLContextState(XMLContextState xcs) {
        synchronized(this) {
            this.contextState = xcs;
        }
    }

    /**
     * INTERNAL: Add and initialize a new session to the list of sessions
     * associated with this XMLContext.
     */
    public void addSession(DatabaseSession sessionToAdd) {
        getXMLContextState().addSession(sessionToAdd);
    }

    /**
     * Create a new XMLUnmarshaller
     *
     * @return An XMLUnmarshaller based on this XMLContext
     */
    @Override
    public XMLUnmarshaller createUnmarshaller() {
        return new XMLUnmarshaller(this);
    }

    /**
     * Create a new XMLUnmarshaller
     * <pre>
     * {@literal Map<String, Boolean> parserFeatures = new HashMap<String, Boolean>(1);}
     * parserFeatures.put("http://apache.org/xml/features/validation/schema/normalized-value", false);
     * XMLUnmarshaller unmarshaller = xmlContext.createUnmarshaller(parserFeatures);
     * </pre>
     * @return An XMLUnmarshaller based on this XMLContext, the underlying
     * parser will use the passed in parser features.
     */
    public XMLUnmarshaller createUnmarshaller(Map<String, Boolean> parserFeatures) {
        return new XMLUnmarshaller(this, parserFeatures);
    }

    /**
     * Create a new XMLBinder
     * @return an XMLBinder based on this XMLContext
     */
    public XMLBinder createBinder() {
        return new XMLBinder(this);
    }

    /**
     * Create a new XMLBinder with supplied marshaller and unmarshaller instances.
     * @return an XMLBinder based on this XMLContext,
     */
    public XMLBinder createBinder(XMLMarshaller marshaller, XMLUnmarshaller unmarshaller) {
        return new XMLBinder(this, marshaller, unmarshaller);
    }

    /**
     * Create a new XMLMarshaller
     *
     * @return An XMLMarshaller based on this XMLContext
     */
    @Override
    public XMLMarshaller createMarshaller() {
        return new XMLMarshaller(this);
    }

    /**
     * Create a new XMLValidator
     *
     * @return An XMLValidator based on this XMLContext
     */
    public XMLValidator createValidator() {
        return new XMLValidator(this);
    }

    /**
     * INTERNAL: Return the session corresponding to this object. Since the
     * object may be mapped by more that one of the projects used to create the
     * XML Context, this method will return the first match.
     *
     * The session will be a unit of work if document preservation is not
     * enabled.  This method will typically  be used for unmarshalling
     * when a non-shared cache is desired.
     */
    public AbstractSession getReadSession(Object object) {
        return getSession(object);
    }

    /**
     * INTERNAL:
     * Return the session corresponding to this class. Since the class
     * may be mapped by more that one of the projects used to create the XML
     * Context, this method will return the first match.
     *
     * The session will be a unit of work if document preservation is not
     * enabled.  This method will typically  be used for unmarshalling
     * when a non-shared cache is desired.
     */
    public AbstractSession getReadSession(Class clazz) {
        return super.getSession(clazz);
    }

    /**
     * INTERNAL:
     * Return the session corresponding to this XMLDescriptor. Since
     * the class may be mapped by more that one of the projects used to create
     * the XML Context, this method will return the first match.
     *
     * The session will be a unit of work if document preservation is not
     * enabled.  This method will typically  be used for unmarshalling
     * when a non-shared cache is desired.
     */
    public AbstractSession getReadSession(XMLDescriptor xmlDescriptor) {
        return super.getSession(xmlDescriptor);
    }

    /**
     * INTERNAL: Return the EclipseLink session used to marshal.
     */
    public List getSessions() {
        return getXMLContextState().getSessions();
    }

    /**
     * INTERNAL: <code>
     * XMLContext xmlContext = new XMLContext("path0:path1");<br>
     * DatabaseSession session = xmlContext.getSession(0);  // returns session for path0<br>
     * </code>
     */
    public DatabaseSession getSession(int index) {
        return getXMLContextState().getSession(index);
    }

    /**
     * INTERNAL: Return the session corresponding to this object. Since the
     * object may be mapped by more that one of the projects used to create the
     * XML Context, this method will return the first match.
     */
    @Override
    public AbstractSession getSession(Object object) {
        return super.getSession(object);
    }

    /**
     * INTERNAL: Return the session corresponding to this class. Since the class
     * may be mapped by more that one of the projects used to create the XML
     * Context, this method will return the first match.
     */
    @Override
    public AbstractSession getSession(Class clazz) {
        return super.getSession(clazz);
    }

    /**
     * INTERNAL: Return the session corresponding to this XMLDescriptor. Since
     * the class may be mapped by more that one of the projects used to create
     * the XML Context, this method will return the first match.
     */
    @Override
    public AbstractSession getSession(XMLDescriptor xmlDescriptor) {
        return super.getSession(xmlDescriptor);
    }

    /**
     * INTERNAL:
     */
    public void storeXMLDescriptorByQName(XMLDescriptor xmlDescriptor) {
        contextState.storeDescriptorByQName(xmlDescriptor, null, null);
    }

    /**
     * INTERNAL: Return the XMLDescriptor with the default root mapping matching
     * the QName parameter.
     */
    @Override
    public XMLDescriptor getDescriptor(QName qName) {
        return super.getDescriptor(qName);
    }

    /**
     * INTERNAL: Return the XMLDescriptor with the default root mapping matching
     * the QName parameter.
     */
    @Override
    public XMLDescriptor getDescriptor(XPathQName xpathQName) {
        return super.getDescriptor(xpathQName);
    }

    public void addDescriptorByQName(QName qName, XMLDescriptor descriptor) {
        contextState.addDescriptorByQName(qName, descriptor);
    }

    /**
     * INTERNAL: Return the XMLDescriptor mapped to the global type matching the
     * XPathFragment parameter.
     */
    @Override
    public XMLDescriptor getDescriptorByGlobalType(XPathFragment xPathFragment) {
        return super.getDescriptorByGlobalType(xPathFragment);
    }

    /**
     * INTERNAL:
     * Return the DocumentPreservationPolicy associated with this session
     * @param session
     * @return
     */
    public DocumentPreservationPolicy getDocumentPreservationPolicy(AbstractSession session) {
        if (session == null) {
            return null;
        }
        XMLLogin login = (XMLLogin) session.getDatasourceLogin();
        return login.getDocumentPreservationPolicy();
    }

    public void setupDocumentPreservationPolicy(DatabaseSession session) {
        getXMLContextState().setupDocumentPreservationPolicy(session);
    }

    /**
     * INTERNAL:
     * Return true if any session held onto by this context has a document preservation
     * policy that requires unmarshalling from a Node.
     */
    @Override
    public boolean hasDocumentPreservation() {
        return getXMLContextState().hasDocumentPreservation();
    }

    /**
    * ADVANCED:
    * Adjust the OXM metadata to take into account ORM mapping metadata,
    */
    public void applyORMMetadata(AbstractSession ormSession) {
        //Iterate over the ORM descriptors and check for matching OXM descriptors
        Iterator ormDescriptors = ormSession.getDescriptors().values().iterator();
        while(ormDescriptors.hasNext()) {
            ClassDescriptor ormDescriptor = (ClassDescriptor)ormDescriptors.next();
            Class javaClass = ormDescriptor.getJavaClass();
            AbstractSession oxmSession = null;
            try {
                oxmSession = this.getSession(javaClass);
            } catch(XMLMarshalException ex) {
                //if we couldn't find a session for this class, we
                //don't have an OX descriptor for it.
            }
            if(oxmSession != null) {
                ClassDescriptor oxmDescriptor = oxmSession.getDescriptor(javaClass);
                //If we have an oxmDescriptor for this ORM descriptor, iterate over
                //mappings, and update the required OXM mappings attribute accessors
                Iterator<DatabaseMapping> ormMappings = ormDescriptor.getMappings().iterator();
                while(ormMappings.hasNext()) {
                    DatabaseMapping ormMapping = ormMappings.next();
                    Mapping oxmMapping = (Mapping) oxmDescriptor.getMappingForAttributeName(ormMapping.getAttributeName());
                    if(oxmMapping != null) {
                        CoreAttributeAccessor oxmAccessor = oxmMapping.getAttributeAccessor();
                        OrmAttributeAccessor newAccessor = new OrmAttributeAccessor(ormMapping.getAttributeAccessor(), oxmAccessor);
                        if(ormMapping.isOneToOneMapping() && ((OneToOneMapping)ormMapping).usesIndirection()) {
                            newAccessor.setValueHolderProperty(true);
                        }
                        newAccessor.setChangeTracking(ormDescriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy());
                        oxmMapping.setAttributeAccessor(newAccessor);

                        //check to see if we need to deal with containerAccessor
                        CoreAttributeAccessor containerAccessor = null;
                        Class containerClass = null;
                        if(oxmMapping.isAbstractCompositeObjectMapping()) {
                            containerAccessor = ((CompositeObjectMapping)oxmMapping).getInverseReferenceMapping().getAttributeAccessor();
                            containerClass = ((CompositeObjectMapping)oxmMapping).getReferenceClass();
                        } else if(oxmMapping.isAbstractCompositeCollectionMapping()) {
                            containerAccessor = ((CompositeCollectionMapping)oxmMapping).getInverseReferenceMapping().getAttributeAccessor();
                            containerClass = ((CompositeCollectionMapping)oxmMapping).getReferenceClass();
                        }
                        if(containerAccessor != null) {
                            ClassDescriptor containerDescriptor = ormSession.getDescriptor(containerClass);
                            if(containerDescriptor != null) {
                                DatabaseMapping ormContainerMapping = containerDescriptor.getMappingForAttributeName(containerAccessor.getAttributeName());
                                if(ormContainerMapping != null) {
                                    //Check for indirection on the container mapping
                                    OrmAttributeAccessor ormAccessor = new OrmAttributeAccessor(ormContainerMapping.getAttributeAccessor(), containerAccessor);
                                    ormAccessor.setChangeTracking(containerDescriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy());
                                    ormAccessor.setValueHolderProperty(ormContainerMapping instanceof OneToOneMapping && ((OneToOneMapping)ormContainerMapping).usesIndirection());
                                    if(oxmMapping.isAbstractCompositeObjectMapping()) {
                                        ((CompositeObjectMapping)oxmMapping).getInverseReferenceMapping().setAttributeAccessor(ormAccessor);
                                    } else if(oxmMapping.isAbstractCompositeCollectionMapping()) {
                                        ((CompositeCollectionMapping)oxmMapping).getInverseReferenceMapping().setAttributeAccessor(ormAccessor);
                                    }

                                }
                            }
                        }
                    }
                }
                Iterator<DatabaseMapping> oxmMappingsIterator = oxmDescriptor.getMappings().iterator();
                while(oxmMappingsIterator.hasNext()) {
                    //iterate over the oxm mappings. Any ReferenceMappings that have a
                    //collection as a backpointer, check to see if the container policy
                    //needs to be matched with the ORM project
                    DatabaseMapping nextMapping = oxmMappingsIterator.next();
                    if(nextMapping instanceof ObjectReferenceMapping) {
                        ObjectReferenceMapping refMapping = (ObjectReferenceMapping)nextMapping;
                        if(refMapping.getInverseReferenceMapping().getAttributeAccessor() != null && refMapping.getInverseReferenceMapping().getContainerPolicy() != null) {
                            ClassDescriptor refDescriptor = ormSession.getClassDescriptor(refMapping.getReferenceClass());
                            if(refDescriptor != null) {
                                DatabaseMapping backpointerMapping =refDescriptor.getMappingForAttributeName(refMapping.getInverseReferenceMapping().getAttributeName());
                                if(backpointerMapping != null && backpointerMapping.isCollectionMapping()) {
                                    refMapping.getInverseReferenceMapping().getContainerPolicy().setContainerClass(backpointerMapping.getContainerPolicy().getContainerClass());
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * <p>Query the object model based on the corresponding XML document.  The following pairings are equivalent:</p>
     *
     * <i>Return the Customer's ID</i>
     * <pre> Integer id = xmlContext.getValueByXPath(customer, "@id", null, Integer.class);
     * Integer id = customer.getId();</pre>
     *
     * <i>Return the Customer's Name</i>
     * <pre> String name = xmlContext.getValueByXPath(customer, "ns:personal-info/ns:name/text()", null, String.class);
     * String name = customer.getName();</pre>
     *
     * <i>Return the Customer's Address</i>
     * <pre> Address address = xmlContext.getValueByXPath(customer, "ns:contact-info/ns:address", aNamespaceResolver, Address.class);
     * Address address = customer.getAddress();</pre>
     *
     * <i>Return all the Customer's PhoneNumbers</i>
     * <pre> List phoneNumbers = xmlContext.getValueByXPath(customer, "ns:contact-info/ns:phone-number", aNamespaceResolver, List.class);
     * List phoneNumbers = customer.getPhoneNumbers();</pre>
     *
     * <i>Return the Customer's second PhoneNumber</i>
     * <pre> PhoneNumber phoneNumber = xmlContext.getValueByXPath(customer, "ns:contact-info/ns:phone-number[2]", aNamespaceResolver, PhoneNumber.class);
     * PhoneNumber phoneNumber = customer.getPhoneNumbers().get(1);</pre>
     *
     * <i>Return the base object</i>
     * <pre> Customer customer = xmlContext.getValueByXPath(customer, ".", aNamespaceResolver, Customer.class);
     * Customer customer = customer;
     * </pre>
     *
     * @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 NamespaceResolver 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.
     */
    @Override
    public <T> T getValueByXPath(Object object, String xPath, NamespaceResolver namespaceResolver, Class<T> returnType) {
        return super.getValueByXPath(object, xPath, namespaceResolver, returnType);
    }

    /**
     * <p>Set values in the object model based on the corresponding XML document.  The following pairings are equivalent:</p>
     *
     * <i>Set the Customer's ID</i>
     * <pre> xmlContext.setValueByXPath(customer, "@id", null, Integer.valueOf(123));
     * customer.setId(Integer.valueOf(123));</pre>
     *
     * <i>Set the Customer's Name</i>
     * <pre> xmlContext.setValueByXPath(customer, "ns:personal-info/ns:name/text()", aNamespaceResolver, "Jane Doe");
     * customer.setName("Jane Doe");</pre>
     *
     * <i>Set the Customer's Address</i>
     * <pre> xmlContext.setValueByXPath(customer, "ns:contact-info/ns:address", aNamespaceResolver, anAddress);
     * customer.setAddress(anAddress);</pre>
     *
     * <i>Set the Customer's PhoneNumbers</i>
     * <pre> xmlContext.setValueByXPath(customer, "ns:contact-info/ns:phone-number", aNamespaceResolver, phoneNumbers);
     * customer.setPhoneNumbers(phoneNumbers);</pre>
     *
     * <i>Set the Customer's second PhoneNumber</i>
     * <pre> xmlContext.setValueByXPath(customer, "ns:contact-info/ns:phone-number[2]", aNamespaceResolver, aPhoneNumber);
     * customer.getPhoneNumbers().get(1);</pre>
     *
     * @param object  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 value The value to be set.
     */
    @Override
    public void setValueByXPath(Object object, String xPath, NamespaceResolver namespaceResolver, Object value) {
        super.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) throws IllegalArgumentException {
        QName qName = new QName(namespace, typeName);
        XMLDescriptor d = null;
        if (!isGlobalType) {
            d = getDescriptor(qName);
        } else {
            XPathFragment frag = new XPathFragment();
            frag.setNamespaceURI(namespace);
            frag.setLocalName(typeName);

            d = getDescriptorByGlobalType(frag);
        }

        if (d == null) {
            return null;
        }

        return d.getInstantiationPolicy().buildNewInstance();
    }

    /**
     * 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.
     */
    @Override
    public <T> T createByXPath(Object parentObject, String xPath, NamespaceResolver namespaceResolver, Class<T> returnType) {
        return super.createByXPath(parentObject, xPath, namespaceResolver, returnType);
    }


    private static class XMLContextState extends ContextState<AbstractSession, XMLDescriptor, Project, DatabaseSession, SessionEventListener> {

        private List<DatabaseSession> sessions;
        private boolean hasDocumentPreservation = false;

        protected XMLContextState(XMLContext xmlContext, Collection<Project> projects, ClassLoader classLoader) {
            this.context = xmlContext;
            sessions = new ArrayList(projects.size());
            Iterator<Project> iterator = projects.iterator();
            while (iterator.hasNext()) {
                Project project = iterator.next();
                preLogin(project, classLoader);
                DatabaseSession session = project.createDatabaseSession();

                // turn logging for this session off and leave the global
                // session up
                // Note: setting level to SEVERE or WARNING will printout
                // stacktraces for expected exceptions
                session.setLogLevel(SessionLog.OFF);
                // don't turn off global static logging
                // AbstractSessionLog.getLog().log(AbstractSessionLog.INFO,
                // "ox_turn_global_logging_off", getClass());
                // AbstractSessionLog.getLog().setLevel(AbstractSessionLog.OFF);
                setupSession(session);
                sessions.add(session);
                storeDescriptorsByQName(session);
            }
        }

        private XMLContextState(XMLContext xmlContext, String sessionNames, ClassLoader classLoader, String xmlResource) {
            super();
            this.context = xmlContext;
            XMLSessionConfigLoader loader = null;
            if (xmlResource != null) {
                loader = new XMLSessionConfigLoader(xmlResource);
            } else {
                loader = new XMLSessionConfigLoader();
            }
            descriptorsByQName = new HashMap();
            descriptorsByGlobalType = new HashMap();
            StringTokenizer st = new StringTokenizer(sessionNames, ":");
            sessions = new ArrayList(st.countTokens());
            int index = 0;
            while (st.hasMoreTokens()) {
                sessions.add(buildSession(st.nextToken(), classLoader, loader));
                index++;
            }
            for (int x = index - 1; x >= 0; x--) {
                storeDescriptorsByQName(sessions.get(x));
            }
        }

        protected XMLContextState(XMLContext xmlContext, Project project,
                ClassLoader classLoader,
                Collection<SessionEventListener> sessionEventListeners) {
            super(xmlContext, project, classLoader, sessionEventListeners);
        }

        /**
         * INTERNAL: Add and initialize a new session to the list of sessions
         * associated with this XMLContext.
         */
        private void addSession(DatabaseSession sessionToAdd) {
            if ((sessionToAdd.getDatasourceLogin() == null) || !(sessionToAdd.getDatasourceLogin().getDatasourcePlatform() instanceof XMLPlatform)) {
                XMLPlatform platform = new SAXPlatform();
                sessionToAdd.setLogin(new XMLLogin(platform));
            }
            DatabaseSession session = sessionToAdd.getProject().createDatabaseSession();
            if (sessionToAdd.getEventManager().hasListeners()) {
                List<SessionEventListener> listeners = sessionToAdd.getEventManager().getListeners();
                int listenersSize = listeners.size();
                for (int x = 0; x < listenersSize; x++) {
                    session.getEventManager().addListener(listeners.get(x));
                }
            }
            session.setExceptionHandler(sessionToAdd.getExceptionHandler());
            session.setLogLevel(SessionLog.OFF);
            setupSession(session);
            if(null == sessions) {
                sessions = new ArrayList<>();
            }
            if(null != this.session) {
                sessions.add(this.session);
            }
            sessions.add(session);

            storeDescriptorsByQName(session);
        }

        @Override
        protected void setupSession(DatabaseSession session) {
            session.setLogLevel(SessionLog.OFF);
            session.login();
            setupDocumentPreservationPolicy(session);
        }

        private DatabaseSession buildSession(String sessionName, ClassLoader classLoader, XMLSessionConfigLoader sessionLoader) throws XMLMarshalException {
            DatabaseSession dbSession;
            if (classLoader != null) {
                dbSession = (DatabaseSession) SessionManager.getManager().getSession(sessionLoader, sessionName, classLoader, false, true);
            } else {
                dbSession = (DatabaseSession) SessionManager.getManager().getSession(sessionLoader, sessionName, privilegedGetClassLoaderForClass(this.getClass()), false, false, false);
            }
            if ((dbSession.getDatasourceLogin() == null) || !(dbSession.getDatasourceLogin().getDatasourcePlatform() instanceof XMLPlatform)) {
                XMLPlatform platform = new SAXPlatform();
                dbSession.setLogin(new XMLLogin(platform));
            }
            DatabaseSession session = dbSession.getProject().createDatabaseSession();
            if (dbSession.getEventManager().hasListeners()) {
                List<SessionEventListener> listeners = dbSession.getEventManager().getListeners();
                int listenersSize = listeners.size();
                for (int x = 0; x < listenersSize; x++) {
                    session.getEventManager().addListener(listeners.get(x));
                }
            }
            session.setExceptionHandler(dbSession.getExceptionHandler());
            session.setLogLevel(SessionLog.OFF);
            setupDocumentPreservationPolicy(session);
            session.login();
            return session;
        }

        @Override
        protected DatabaseSession getSession() {
            if(null == sessions) {
                return super.getSession();
            }
            return sessions.get(0);
        }

        /**
         * INTERNAL: Return the session corresponding to this class. Since the class
         * may be mapped by more that one of the projects used to create the XML
         * Context, this method will return the first match.
         */
        @Override
        protected AbstractSession getSession(Class clazz) {
            if (null == clazz) {
                return null;
            }
            if (null == sessions) {
                return super.getSession(clazz);
            }
            for (int x = 0, numberOfSessions = sessions.size(); x < numberOfSessions; x++) {
                AbstractSession next = ((AbstractSession) sessions.get(x));
                if (next.getDescriptor(clazz) != null) {
                    return next;
                }
            }
            throw XMLMarshalException.descriptorNotFoundInProject(clazz.getName());
        }

        /**
         * INTERNAL: Return the session corresponding to this XMLDescriptor. Since
         * the class may be mapped by more that one of the projects used to create
         * the XML Context, this method will return the first match.
         */
        @Override
        protected AbstractSession getSession(XMLDescriptor xmlDescriptor) {
            if (null == xmlDescriptor) {
                return null;
            }
            if(null == sessions) {
                return super.getSession(xmlDescriptor);
            }
            for (int x = 0, numberOfSessions = sessions.size(); x < numberOfSessions; x++) {
                AbstractSession next = ((AbstractSession) sessions.get(x));
                if (next.getProject().getOrderedDescriptors().contains(xmlDescriptor)) {
                    return next;
                }
            }
            throw XMLMarshalException.descriptorNotFoundInProject(xmlDescriptor.getJavaClass().getName());
        }

        private List<DatabaseSession> getSessions() {
            if(null == sessions) {
                return Collections.singletonList(session);
            }
            return sessions;
        }

        /**
         * INTERNAL: <code>
         * XMLContext xmlContext = new XMLContext("path0:path1");<br>
         * DatabaseSession session = xmlContext.getSession(0);  // returns session for path0<br>
         * </code>
         */
        private DatabaseSession getSession(int index) {
            if (null == sessions) {
                return session;
            }
            return sessions.get(index);
        }

        /**
         * INTERNAL: Return the session corresponding to this object. Since the
         * object may be mapped by more that one of the projects used to create the
         * XML Context, this method will return the first match.
         */
        @Override
        protected AbstractSession getSession(Object object) {
            if (null == object) {
                return null;
            }
            if (null == sessions) {
                return super.getSession(object);
            }
            for (int x = 0, numberOfSessions = sessions.size(); x < numberOfSessions; x++) {
                AbstractSession next = ((AbstractSession) sessions.get(x));
                if (next.getDescriptor(object) != null) {
                    return next;
                }
            }
            throw XMLMarshalException.descriptorNotFoundInProject(object.getClass().getName());
        }

        /**
         * INTERNAL:
         * Return true if any session held onto by this context has a document preservation
         * policy that requires unmarshalling from a Node.
         */
        private boolean hasDocumentPreservation() {
            return this.hasDocumentPreservation;
        }

        @Override
        protected void preLogin(Project project, ClassLoader classLoader) {
            if ((project.getDatasourceLogin() == null) || !(project.getDatasourceLogin().getDatasourcePlatform() instanceof XMLPlatform)) {
                XMLPlatform platform = new SAXPlatform();
                platform.getConversionManager().setLoader(classLoader);
                project.setLogin(new XMLLogin(platform));
            }
        }

        private void setupDocumentPreservationPolicy(DatabaseSession session) {
            XMLLogin login = (XMLLogin) session.getDatasourceLogin();
            if (login.getDocumentPreservationPolicy() == null) {
                Iterator iterator = session.getProject().getOrderedDescriptors().iterator();
                while (iterator.hasNext()) {
                    Descriptor xmlDescriptor = (Descriptor) iterator.next();
                    if (xmlDescriptor.shouldPreserveDocument()) {
                        login.setDocumentPreservationPolicy(new DescriptorLevelDocumentPreservationPolicy());
                        break;
                    }
                }
            }
            if (login.getDocumentPreservationPolicy() == null) {
                login.setDocumentPreservationPolicy(new NoDocumentPreservationPolicy());
            }

            login.getDocumentPreservationPolicy().initialize(context);

            if (login.getDocumentPreservationPolicy().shouldPreserveDocument() && !hasDocumentPreservation) {
                hasDocumentPreservation = true;
            }
        }

    }

    @Override
    protected XMLField createField(String path) {
        if(null == path) {
            return new XMLField();
        }
        return new XMLField(path);
    }

    /**
     * Returns descriptors from all sessions.
     *
     * @return descriptors from all sessions
     */
    public List<Descriptor> getDescriptors() {
        List<Descriptor> descriptors = new ArrayList<>();
        List<Session> sessions = getSessions();
        for (Session session : sessions) {
            List<Descriptor> orderedDescriptors = (List) session.getProject().getOrderedDescriptors();
            for (Descriptor xDesc : orderedDescriptors) {
                descriptors.add(xDesc);
            }
        }
        return descriptors;
    }

    /**
     * Returns conversion manager from session datasource platform.
     *
     * @return conversion manager
     */
    public ConversionManager getOxmConversionManager() {
        return (org.eclipse.persistence.internal.oxm.ConversionManager) getSession().getDatasourcePlatform().getConversionManager();
    }

    /**
     * Returns descriptor for given object.
     *
     * @param object
     * @return descriptor for given object
     */
    public Descriptor getDescriptorForObject(Object object) {
        Session session = getSession(object);
        if (null != session && null != session.getDescriptor(object)) {
            return (Descriptor)session.getDescriptor(object);
        }

        return null;
    }

    private static ClassLoader privilegedGetClassLoaderForClass(final Class clazz) {
        if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
            try {
                return AccessController.doPrivileged(new PrivilegedGetClassLoaderForClass(clazz));
            } catch (PrivilegedActionException ex) {
                throw (RuntimeException) ex.getCause();
            }
        }
        return PrivilegedAccessHelper.getClassLoaderForClass(clazz);
    }

}
