/*
 * 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.0 - added case insensitive unmarshalling property,
//                             added Bean Validation support.
package org.eclipse.persistence.jaxb;

import java.io.File;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.StringTokenizer;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.UnmarshalException;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.UnmarshallerHandler;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import jakarta.xml.bind.attachment.AttachmentUnmarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.Source;
import javax.xml.validation.Schema;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.exceptions.BeanValidationException;
import org.eclipse.persistence.exceptions.XMLMarshalException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.jaxb.IDResolverWrapper;
import org.eclipse.persistence.internal.jaxb.ObjectGraphImpl;
import org.eclipse.persistence.internal.jaxb.WrappedValue;
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.StrBuffer;
import org.eclipse.persistence.internal.oxm.XMLConversionManager;
import org.eclipse.persistence.internal.oxm.mappings.Descriptor;
import org.eclipse.persistence.internal.oxm.mappings.DirectCollectionMapping;
import org.eclipse.persistence.internal.oxm.record.XMLEventReaderInputSource;
import org.eclipse.persistence.internal.oxm.record.XMLEventReaderReader;
import org.eclipse.persistence.internal.oxm.record.XMLStreamReaderInputSource;
import org.eclipse.persistence.internal.oxm.record.XMLStreamReaderReader;
import org.eclipse.persistence.internal.oxm.record.namespaces.PrefixMapperNamespaceResolver;
import org.eclipse.persistence.jaxb.JAXBContext.RootLevelXmlAdapter;
import org.eclipse.persistence.jaxb.attachment.AttachmentUnmarshallerAdapter;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.LogLevel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.IDResolver;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLUnmarshaller;
import org.eclipse.persistence.oxm.record.UnmarshalRecord;
import org.w3c.dom.Node;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

/**
 * INTERNAL:
 * <p><b>Purpose:</b>To Provide an implementation of the JAXB 2.0 Unmarshaller Interface
 * <p><b>Responsibilities:</b>
 * <ul>
 * <li>Provide a JAXB wrapper on the XMLUnmarshaller API</li>
 * <li>Perform XML to Object Conversions</li>
 * </ul>
 * <p>This implementation of the JAXB 2.1/2.2 Unmarshaller interface provides the required functionality
 * by acting as a thin wrapper on the existing XMLMarshaller API.
 *
 * @author mmacivor
 * @since Oracle TopLink 11.1.1.0.0
 * @see jakarta.xml.bind.Unmarshaller
 * @see org.eclipse.persistence.jaxb.UnmarshallerProperties
 * @see org.eclipse.persistence.oxm.XMLUnmarshaller
 */
public class JAXBUnmarshaller implements Unmarshaller {

    private JAXBBeanValidator beanValidator;

    private BeanValidationMode beanValidationMode;

    // The actual type is ValidatorFactory. It's done due to optional nature of jakarta.validation.
    private Object prefValidatorFactory;
    private boolean bvNoOptimisation = false;
    private Class<?>[] beanValidationGroups;

    private final XMLUnmarshaller xmlUnmarshaller;
    private final JAXBContext jaxbContext;
    private ValidationEventHandler validationEventHandler;

    public static final String XML_JAVATYPE_ADAPTERS = "xml-javatype-adapters";
    public static final String STAX_SOURCE_CLASS_NAME = "javax.xml.transform.stax.StAXSource";

    private static final String SUN_ID_RESOLVER = "org.glassfish.jaxb.IDResolver";
    private static final String SUN_JSE_ID_RESOLVER = "com.sun.xml.internal.bind.IDResolver";

    public JAXBUnmarshaller(XMLUnmarshaller newXMLUnmarshaller, JAXBContext jaxbContext) {
        this.jaxbContext = jaxbContext;
        validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
        beanValidationMode = BeanValidationMode.AUTO;
        if (BeanValidationChecker.isBeanValidationPresent()) {
            beanValidator = JAXBBeanValidator.getUnmarshallingBeanValidator(this.jaxbContext);
        }
        xmlUnmarshaller = newXMLUnmarshaller;
        xmlUnmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
        xmlUnmarshaller.setUnmarshalListener(new JAXBUnmarshalListener(this));
        xmlUnmarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
        // Disable any warning exceptions when an unmapped element is found, if the
        // validationEventHandler and errorHandler are set to default values
        xmlUnmarshaller.setWarnOnUnmappedElement(false);
    }

    public XMLUnmarshaller getXMLUnmarshaller() {
        return xmlUnmarshaller;
    }

    @Override
    public Object unmarshal(File file) throws JAXBException {
        try {
            Object value = xmlUnmarshaller.unmarshal(file);
            return validateAndTransformIfRequired(value); // xml object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }



    @Override
    public Object unmarshal(InputStream inputStream) throws JAXBException {
        try {
            if (xmlUnmarshaller.isAutoDetectMediaType() || xmlUnmarshaller.getMediaType() == MediaType.APPLICATION_JSON || null == jaxbContext.getXMLInputFactory() || XMLUnmarshaller.NONVALIDATING != xmlUnmarshaller.getValidationMode()) {
                return validateAndTransformIfRequired(xmlUnmarshaller.unmarshal(inputStream)); // xml bindings + object inside inputStream
            } else {
                if (null == inputStream) {
                    throw XMLMarshalException.nullArgumentException();
                }
                XMLStreamReader xmlStreamReader;
                xmlStreamReader = jaxbContext.getXMLInputFactory().createXMLStreamReader(inputStream);
                Object value = unmarshal(xmlStreamReader);
                xmlStreamReader.close();
                return value;
            }
        } catch(JAXBException jaxbException) {
            throw jaxbException;
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (Exception exception) {
            throw new UnmarshalException(exception);
        }
    }

    @Override
    public Object unmarshal(URL url) throws JAXBException {
        try {
            Object value = xmlUnmarshaller.unmarshal(url);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    @Override
    public Object unmarshal(InputSource inputSource) throws JAXBException {
        try {
            Object value = xmlUnmarshaller.unmarshal(inputSource);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    @Override
    public Object unmarshal(Reader reader) throws JAXBException {

        try {
            if (xmlUnmarshaller.isAutoDetectMediaType()   || xmlUnmarshaller.getMediaType() == MediaType.APPLICATION_JSON || null == jaxbContext.getXMLInputFactory() || XMLUnmarshaller.NONVALIDATING != xmlUnmarshaller.getValidationMode()) {

                return validateAndTransformIfRequired(xmlUnmarshaller.unmarshal(reader)); // xml bindings + object inside reader
            } else {
                if (null == reader) {
                    throw XMLMarshalException.nullArgumentException();
                }
                XMLStreamReader xmlStreamReader = jaxbContext.getXMLInputFactory().createXMLStreamReader(reader);
                Object value = unmarshal(xmlStreamReader);
                xmlStreamReader.close();
                return value;
            }
        } catch(JAXBException jaxbException) {
            throw jaxbException;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception exception) {
            throw new UnmarshalException(exception);
        }
    }

    @Override
    public Object unmarshal(Node node) throws JAXBException {
        try {
            Object value = xmlUnmarshaller.unmarshal(node);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    private JAXBElement validateAndBuildJAXBElement(Object obj, Class declaredClass) throws BeanValidationException {
        if (beanValidator != null && beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
            beanValidator.validate(obj, beanValidationGroups);
        }
        return buildJAXBElementFromObject(obj, declaredClass);
    }

    /**
     * Create a JAXBElement instance.  If the object is an instance
     * of XMLRoot, we will use its field values to create the
     * JAXBElement.  If the object is not an XMLRoot instance, we
     * will have to determine the 'name' value.  This will be done
     * using the object's descriptor default root element - any
     * prefix will be resolved, and a QName created.
     *
     */
    private JAXBElement buildJAXBElementFromObject(Object obj, Class declaredClass) {
        // if an XMLRoot was returned, the root element != the default root
        // element of the object being marshalled to - need to create a
        // JAXBElement from the returned XMLRoot object
        if (obj instanceof Root) {
            JAXBElement jaxbElement = jaxbContext.createJAXBElementFromXMLRoot(((Root)obj), declaredClass);
            if(((Root)obj).isNil()) {
                jaxbElement.setNil(((Root)obj).isNil());
                jaxbElement.setValue(null);
            }
            return jaxbElement;
        }

        if(obj instanceof JAXBElement) {
            return (JAXBElement) obj;
        }

        // at this point, the default root element of the object being marshalled
        // to == the root element - here we need to create a JAXBElement
        // instance using information from the returned object
        org.eclipse.persistence.sessions.Session sess = xmlUnmarshaller.getXMLContext().getSession(obj);
        Descriptor desc = (Descriptor) sess.getClassDescriptor(obj);

        // here we are assuming that if we've gotten this far, there
        // must be a default root element set on the descriptor.  if
        // this is incorrect, we need to check for null and throw an
        // exception
        String rootName = desc.getDefaultRootElement();
        if (rootName == null) {
            return jaxbContext.createJAXBElement(new QName(""), obj.getClass(), obj);
        }
        String rootNamespaceUri = null;
        int idx = rootName.indexOf(':');
        if (idx != -1) {
            rootNamespaceUri = desc.getNamespaceResolver().resolveNamespacePrefix(rootName.substring(0, idx));
            rootName = rootName.substring(idx + 1);
        }

        QName qname;
        if (rootNamespaceUri == null) {
            qname = new QName(rootName);
        } else {
            qname = new QName(rootNamespaceUri, rootName);
        }
        if(declaredClass != null){
            return jaxbContext.createJAXBElement(qname, declaredClass, obj);
        }else{
            return jaxbContext.createJAXBElement(qname, obj.getClass(), obj);
        }
    }

    @Override
    public JAXBElement unmarshal(Node node, Class javaClass) throws JAXBException {
        if(null == javaClass) {
            throw new IllegalArgumentException();
        }
        try {
            Class classToUnmarshalTo = getClassToUnmarshalTo(javaClass);
            if(jaxbContext.getArrayClassesToGeneratedClasses() != null) {
                Class generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(javaClass.getCanonicalName());
                if(generatedClass != null){
                    classToUnmarshalTo = generatedClass;
                }
            }
            return validateAndBuildJAXBElement(xmlUnmarshaller.unmarshal(node, classToUnmarshalTo), javaClass); // xmlbindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    @Override
    public Object unmarshal(Source source) throws JAXBException {
        try {
            Object value = xmlUnmarshaller.unmarshal(source);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    @Override
    public JAXBElement unmarshal(Source source, Class javaClass) throws JAXBException {
        if(null == javaClass) {
            throw new IllegalArgumentException();
        }
        Class classToUnmarshalTo = getClassToUnmarshalTo(javaClass);

        try {
            return validateAndBuildJAXBElement(xmlUnmarshaller.unmarshal(source, classToUnmarshalTo), javaClass); // json object + xml bindings
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    private JAXBElement unmarshal(Source source, Class javaClass, Class declaredType) {
        Class classToUnmarshalTo = javaClass;
        if(jaxbContext.getArrayClassesToGeneratedClasses() != null) {
            Class generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(javaClass.getCanonicalName());
            if(generatedClass != null){
                classToUnmarshalTo = generatedClass;
            }
        }
        return validateAndBuildJAXBElement(xmlUnmarshaller.unmarshal(source, classToUnmarshalTo), declaredType); // never used in tests. (I guess its only for ParameterizedTypes)
    }

    public JAXBElement unmarshal(Source source, Type type) throws JAXBException {
        if(null == type) {
            throw new IllegalArgumentException();
        }
        try {
            if(jaxbContext.getTypeToTypeMappingInfo() != null) {
                TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(type);
                if(tmi != null) {
                    return unmarshal(source, tmi);
                }
            }

            Class unmarshalClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(type);
            if(unmarshalClass != null){
                JAXBElement unmarshalled =  unmarshal(source, unmarshalClass, Object.class);
                Class declaredClass;
                if(type instanceof Class){
                    declaredClass = (Class)type;
                }else{
                    declaredClass = Object.class;
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), unmarshalled.getValue());
                return returnVal;
            }else if(type instanceof Class){
                return  unmarshal(source, (Class)type, Object.class);
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    /**
     * Unmarshal the object based on the binding metadata associated with the
     * TypeMappingInfo.
     */
    public JAXBElement unmarshal(Source source, TypeMappingInfo type) throws JAXBException {
        try {
            Class unmarshalClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(type);
            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
            if(unmarshalClass != null){
                JAXBElement unmarshalled = unmarshal(source, unmarshalClass);
                Class declaredClass = null;
                if(type.getType() instanceof Class){
                    declaredClass = (Class)type.getType();
                }else{
                    declaredClass = Object.class;
                }
                Object value = unmarshalled.getValue();
                if(adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().unmarshal(value);
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), value);
                return returnVal;
            }else if(type.getType() instanceof Class){
                if(adapter != null) {
                    JAXBElement element = unmarshal(source, adapter.getBoundType());
                    try {
                        Object value = adapter.getXmlAdapter().unmarshal(element.getValue());
                        element.setValue(value);
                        return element;
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                return  unmarshal(source, (Class)type.getType());
            } else if(type.getType() instanceof ParameterizedType) {
                return unmarshal(source, ((ParameterizedType)type.getType()).getRawType());
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    @Override
    public JAXBElement unmarshal(XMLStreamReader streamReader, Class javaClass) throws JAXBException {
        if(null == streamReader || null == javaClass) {
            throw new IllegalArgumentException();
        }
        try {
            XMLStreamReaderReader staxReader = new XMLStreamReaderReader(xmlUnmarshaller);
            XMLStreamReaderInputSource inputSource = new XMLStreamReaderInputSource(streamReader);
            if(XMLConversionManager.getDefaultJavaTypes().get(javaClass) != null ||CoreClassConstants.XML_GREGORIAN_CALENDAR.isAssignableFrom(javaClass) ||CoreClassConstants.DURATION.isAssignableFrom(javaClass)) {
                PrimitiveContentHandler primitiveContentHandler = new PrimitiveContentHandler(javaClass);
                staxReader.setContentHandler(primitiveContentHandler);
                staxReader.parse(inputSource);
                return primitiveContentHandler.getJaxbElement();
            }
            Class classToUnmarshalTo = getClassToUnmarshalTo(javaClass);
            JAXBElement unmarshalled = validateAndBuildJAXBElement(xmlUnmarshaller.unmarshal(staxReader, inputSource, classToUnmarshalTo), javaClass); // xmlbindings + object (xmlelement) + "nomappings.SomeClass" + "jaxb.stax.EndEventRoot"

            if(classToUnmarshalTo != javaClass){
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), javaClass, unmarshalled.getScope(), unmarshalled.getValue());
                return returnVal;
            }
            return unmarshalled;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException); // Exception [EclipseLink-25004] cvc-maxInclusive-valid: Value '1234567' is not facet-valid with respect to maxInclusive '999999' for type 'id-type'.
        } catch (Exception e) {
            throw new JAXBException(e);
        }
    }

    public JAXBElement unmarshal(XMLStreamReader streamReader, Type type) throws JAXBException {
        if(null == streamReader || null == type) {
            throw new IllegalArgumentException();
        }
        try {
            if(jaxbContext.getTypeToTypeMappingInfo() != null) {
                TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(type);
                if(tmi != null) {
                    return unmarshal(streamReader, tmi);
                }
            }

            Class unmarshalClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(type);
            if(unmarshalClass != null){
                JAXBElement unmarshalled = unmarshal(streamReader, unmarshalClass);
                Class declaredClass = null;
                if(type instanceof Class){
                    declaredClass = (Class)type;
                }else{
                    declaredClass = Object.class;
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), unmarshalled.getValue());
                return returnVal;

            }else if(type instanceof Class){
                return  unmarshal(streamReader, (Class)type);
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    /**
     * Unmarshal the object based on the binding metadata associated with the
     * TypeMappingInfo.
     */
    public JAXBElement unmarshal(XMLStreamReader streamReader, TypeMappingInfo type) throws JAXBException {
        try {
            Descriptor xmlDescriptor = type.getXmlDescriptor();

            if (type.getType() instanceof Class) {
                Class javaClass = (Class) type.getType();
                Class componentClass = javaClass.getComponentType();
                if (javaClass.isArray() && javaClass != CoreClassConstants.APBYTE && javaClass != CoreClassConstants.ABYTE && XMLConversionManager.getDefaultJavaTypes().get(componentClass) != null) {
                    // Top-level array.  Descriptor will be for an EL-generated class, containing one DirectCollection mapping.
                    DirectCollectionMapping mapping = (DirectCollectionMapping) xmlDescriptor.getMappings().get(0);

                    XMLStreamReaderReader staxReader = new XMLStreamReaderReader(xmlUnmarshaller);
                    staxReader.setErrorHandler(xmlUnmarshaller.getErrorHandler());

                    PrimitiveArrayContentHandler primitiveArrayContentHandler = new PrimitiveArrayContentHandler(javaClass, componentClass, mapping.usesSingleNode());
                    staxReader.setContentHandler(primitiveArrayContentHandler);

                    XMLStreamReaderInputSource inputSource = new XMLStreamReaderInputSource(streamReader);
                    staxReader.parse(inputSource);
                    return primitiveArrayContentHandler.getJaxbElement();
                }
            }

            if(null != xmlDescriptor && null == getSchema()) {
                RootLevelXmlAdapter adapter= null;
                if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() >0){
                    adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
                }
                UnmarshalRecord wrapper = (UnmarshalRecord) xmlDescriptor.getObjectBuilder().createRecordFromXMLContext(xmlUnmarshaller.getXMLContext());
                org.eclipse.persistence.internal.oxm.record.UnmarshalRecord unmarshalRecord = wrapper.getUnmarshalRecord();
                XMLStreamReaderReader staxReader = new XMLStreamReaderReader(xmlUnmarshaller);
                unmarshalRecord.setUnmarshaller(xmlUnmarshaller);
                unmarshalRecord.setXMLReader(staxReader);
                staxReader.setContentHandler(unmarshalRecord);
                staxReader.parse(streamReader);
                Object value = null;
                if(unmarshalRecord.isNil()) {
                    value = null;
                } else {
                    value = unmarshalRecord.getCurrentObject();
                }
                if(value instanceof WrappedValue){
                    value = ((WrappedValue)value).getValue();
                }

                if(value instanceof ManyValue){
                    value = ((ManyValue)value).getItem();
                }
                if(adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().unmarshal(value);
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                Class declaredClass = null;
                if(type.getType() instanceof Class){
                    declaredClass = (Class)type.getType();
                }else{
                    declaredClass = Object.class;
                }
                return new JAXBElement(new QName(unmarshalRecord.getRootElementNamespaceUri(), unmarshalRecord.getLocalName()), declaredClass, value);
            }
            if(jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
                return unmarshal(streamReader, type.getType());
            }
            RootLevelXmlAdapter adapter= null;
            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() >0){
                adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
            }
            Class unmarshalClass = null;
            if(jaxbContext.getTypeMappingInfoToGeneratedType().size() >0){
                unmarshalClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(type);
            }

            if(unmarshalClass != null){
                JAXBElement unmarshalled = unmarshal(streamReader, unmarshalClass);
                Class declaredClass = null;
                if(type.getType() instanceof Class){
                    declaredClass = (Class)type.getType();
                }else{
                    declaredClass = Object.class;
                }
                Object value = unmarshalled.getValue();
                if(adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().unmarshal(value);
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), value);
                return returnVal;
            }else if(type.getType() instanceof Class){
                if(adapter != null) {
                    JAXBElement element = unmarshal(streamReader, adapter.getBoundType());
                    try {
                        Object value = adapter.getXmlAdapter().unmarshal(element.getValue());
                        element.setValue(value);
                        return element;
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                return  unmarshal(streamReader, (Class)type.getType());
            } else if(type.getType() instanceof ParameterizedType) {
                return unmarshal(streamReader, ((ParameterizedType)type.getType()).getRawType());
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (SAXException e) {
            throw new JAXBException(e);
        }
    }

    @Override
    public Object unmarshal(XMLStreamReader streamReader) throws JAXBException {
        if(null == streamReader) {
            throw new IllegalArgumentException();
        }
        try {
            XMLStreamReaderReader staxReader = new XMLStreamReaderReader(xmlUnmarshaller);
            XMLStreamReaderInputSource inputSource = new XMLStreamReaderInputSource(streamReader);
            Object value = xmlUnmarshaller.unmarshal(staxReader, inputSource);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    @Override
    public JAXBElement unmarshal(XMLEventReader eventReader, Class javaClass) throws JAXBException {
        if(null == eventReader || null == javaClass) {
            throw new IllegalArgumentException();
        }
        try {
            Class classToUnmarshalTo = getClassToUnmarshalTo(javaClass);
            XMLEventReaderReader staxReader = new XMLEventReaderReader(xmlUnmarshaller);
            XMLEventReaderInputSource inputSource = new XMLEventReaderInputSource(eventReader);
            JAXBElement unmarshalled =  validateAndBuildJAXBElement(xmlUnmarshaller.unmarshal(staxReader, inputSource, classToUnmarshalTo), javaClass); // json object + xml bindings

            if(classToUnmarshalTo != javaClass){
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), javaClass, unmarshalled.getScope(), unmarshalled.getValue());
                return returnVal;
            }
            return unmarshalled;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    public JAXBElement unmarshal(XMLEventReader eventReader, Type type) throws JAXBException {
        if(null == eventReader || null == type) {
            throw new IllegalArgumentException();
        }
        try {
            if(jaxbContext.getTypeToTypeMappingInfo() != null) {
                TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(type);
                if(tmi != null) {
                    return unmarshal(eventReader, tmi);
                }
            }
            Class unmarshalClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(type);
            if(unmarshalClass != null){
                JAXBElement unmarshalled = unmarshal(eventReader, unmarshalClass);
                Class declaredClass = null;
                if(type instanceof Class){
                    declaredClass = (Class)type;
                }else{
                    declaredClass = Object.class;
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), unmarshalled.getValue());
                return returnVal;
            }else if(type instanceof Class){
                return  unmarshal(eventReader, (Class)type);
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    /**
     * Unmarshal the object based on the binding metadata associated with the
     * TypeMappingInfo.
     */
    public JAXBElement unmarshal(XMLEventReader eventReader, TypeMappingInfo type) throws JAXBException {
        try {
            if(jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
                return unmarshal(eventReader, type.getType());
            }

            Class unmarshalClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(type);
            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
            if(unmarshalClass != null){
                JAXBElement unmarshalled = unmarshal(eventReader, unmarshalClass);
                Class declaredClass = null;
                if(type.getType() instanceof Class){
                    declaredClass = (Class)type.getType();
                }else{
                    declaredClass = Object.class;
                }
                Object value = unmarshalled.getValue();
                if(adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().unmarshal(value);
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                JAXBElement returnVal = new JAXBElement(unmarshalled.getName(), declaredClass, unmarshalled.getScope(), value);
                return returnVal;
            }else if(type.getType() instanceof Class){
                if(adapter != null) {
                    JAXBElement element = unmarshal(eventReader, adapter.getBoundType());
                    try {
                        Object value = adapter.getXmlAdapter().unmarshal(element.getValue());
                        element.setValue(value);
                        return element;
                    } catch(Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
                return  unmarshal(eventReader, (Class)type.getType());
            } else if(type.getType() instanceof ParameterizedType) {
                return unmarshal(eventReader, ((ParameterizedType)type.getType()).getRawType());
            }
            return null;
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        }
    }

    @Override
    public Object unmarshal(XMLEventReader eventReader) throws JAXBException {
        if(null == eventReader) {
            throw new IllegalArgumentException();
        }
        try {
            XMLEventReaderReader staxReader = new XMLEventReaderReader(xmlUnmarshaller);
            XMLEventReaderInputSource inputSource = new XMLEventReaderInputSource(eventReader);
            Object value = xmlUnmarshaller.unmarshal(staxReader, inputSource);
            return validateAndTransformIfRequired(value); // xml bindings + object
        } catch (XMLMarshalException xmlMarshalException) {
            throw handleXMLMarshalException(xmlMarshalException);
        } catch (BeanValidationException bve) {
            throw new UnmarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        }
    }

    @Override
    public UnmarshallerHandler getUnmarshallerHandler() {
        return new JAXBUnmarshallerHandler(this);
    }

    public void setValidating(boolean validate) throws JAXBException {
        if (validate) {
            xmlUnmarshaller.setValidationMode(XMLUnmarshaller.SCHEMA_VALIDATION);
        } else {
            xmlUnmarshaller.setValidationMode(XMLUnmarshaller.NONVALIDATING);
        }
    }

    public boolean isValidating() throws JAXBException {
        return xmlUnmarshaller.getValidationMode() != XMLUnmarshaller.NONVALIDATING;
    }

    @Override
    public void setEventHandler(ValidationEventHandler newValidationEventHandler) throws JAXBException {
        if (null == newValidationEventHandler) {
            validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
        } else {
            validationEventHandler = newValidationEventHandler;
        }
        xmlUnmarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
        // Disable any warning exceptions when an unmapped element is found, if the
        // validationEventHandler and errorHandler are set to default values
        xmlUnmarshaller.setWarnOnUnmappedElement(validationEventHandler != JAXBContext
                .DEFAULT_VALIDATION_EVENT_HANDLER);
    }

    @Override
    public ValidationEventHandler getEventHandler() throws JAXBException {
        return validationEventHandler;
    }

    /**
     * Set a property on the JAXBUnmarshaller. Attempting to set any unsupported
     * property will result in a jakarta.xml.bind.PropertyException.
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties
     */
    @Override
    public void setProperty(String key, Object value) throws PropertyException {
        if (key == null) {
            throw new IllegalArgumentException();
        }
        SessionLog logger = AbstractSessionLog.getLog();
        if (logger.shouldLog(SessionLog.FINE, SessionLog.MOXY)) {
            logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_set_unmarshaller_property", new Object[] {key, value});
        }
        if (MOXySystemProperties.moxyLogPayload != null && xmlUnmarshaller.isLogPayload() == null) {
            xmlUnmarshaller.setLogPayload(MOXySystemProperties.moxyLogPayload);
        }
        if (key.equals(UnmarshallerProperties.MEDIA_TYPE)) {
            MediaType mType = null;
            if(value instanceof MediaType) {
                mType = (MediaType) value;
            } else if(value instanceof String) {
                mType = MediaType.getMediaType((String)value);
            }
            if(mType == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            xmlUnmarshaller.setMediaType(mType);
        } else if (key.equals(UnmarshallerProperties.UNMARSHALLING_CASE_INSENSITIVE)){
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            xmlUnmarshaller.setCaseInsensitive((Boolean)value);
        } else if (key.equals(UnmarshallerProperties.AUTO_DETECT_MEDIA_TYPE)){
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            xmlUnmarshaller.setAutoDetectMediaType((Boolean)value);
        } else if (key.equals(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX)){
            xmlUnmarshaller.setAttributePrefix((String)value);
        } else if (UnmarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            xmlUnmarshaller.setIncludeRoot((Boolean)value);
        } else if (UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER.equals(key)){
            if (value == null){
                xmlUnmarshaller.setNamespaceResolver(null);
            } else if (value instanceof Map){
                Map<String, String> namespaces = (Map<String, String>)value;
                NamespaceResolver nr = new NamespaceResolver();
                Iterator<Entry<String, String>> namesapcesIter = namespaces.entrySet().iterator();
                for (int i=0;i<namespaces.size(); i++){
                    Entry<String, String> nextEntry = namesapcesIter.next();
                    nr.put(nextEntry.getValue(), nextEntry.getKey());
                }
                xmlUnmarshaller.setNamespaceResolver(nr);
            } else if (value instanceof NamespacePrefixMapper){
                xmlUnmarshaller.setNamespaceResolver(new PrefixMapperNamespaceResolver((NamespacePrefixMapper)value, null));
            }
        } else if (UnmarshallerProperties.JSON_VALUE_WRAPPER.equals(key)){
            xmlUnmarshaller.setValueWrapper((String)value);
        } else if (UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)){
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            xmlUnmarshaller.setNamespaceSeparator((Character)value);
        } else if (UnmarshallerProperties.JSON_USE_XSD_TYPES_WITH_PREFIX.equals(key)) {
            xmlUnmarshaller.getJsonTypeConfiguration().setUseXsdTypesWithPrefix((Boolean)value);
        } else if (UnmarshallerProperties.JSON_TYPE_COMPATIBILITY.equals(key)) {
            xmlUnmarshaller.getJsonTypeConfiguration().setJsonTypeCompatibility((Boolean)value);
        } else if (UnmarshallerProperties.JSON_TYPE_ATTRIBUTE_NAME.equals(key)) {
            xmlUnmarshaller.getJsonTypeConfiguration().setJsonTypeAttributeName((String)value);
        } else if (UnmarshallerProperties.ID_RESOLVER.equals(key)) {
            setIDResolver((IDResolver) value);
        } else if (SUN_ID_RESOLVER.equals(key) || SUN_JSE_ID_RESOLVER.equals(key)) {
            if(value == null){
                setIDResolver(null);
            }else {
                setIDResolver(new IDResolverWrapper(value));
            }
        } else if (UnmarshallerProperties.OBJECT_GRAPH.equals(key)) {
            if(value instanceof ObjectGraphImpl) {
                xmlUnmarshaller.setUnmarshalAttributeGroup(((ObjectGraphImpl) value).getAttributeGroup());
            } else if(value instanceof String || value == null) {
                xmlUnmarshaller.setUnmarshalAttributeGroup(value);
            } else {
                throw org.eclipse.persistence.exceptions.JAXBException.invalidValueForObjectGraph(value);
            }
        } else if (UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
            xmlUnmarshaller.setWrapperAsCollectionName((Boolean) value);
        } else if (UnmarshallerProperties.BEAN_VALIDATION_MODE.equals(key)){
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            this.beanValidationMode = ((BeanValidationMode) value);
        } else if (UnmarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
            // Null value is allowed
            this.prefValidatorFactory = value;
        } else if (UnmarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
            if (value == null) {
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            this.beanValidationGroups = ((Class<?>[]) value);
        } else if (UnmarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            this.bvNoOptimisation = ((boolean) value);
        } else if (UnmarshallerProperties.DISABLE_SECURE_PROCESSING.equals(key)) {
            if(value == null){
                throw new PropertyException(key, Constants.EMPTY_STRING);
            }
            boolean disabled = value instanceof String
                    ? Boolean.parseBoolean((String) value)
                    : (boolean) value;
            xmlUnmarshaller.setDisableSecureProcessing(disabled);
        } else if (UnmarshallerProperties.MOXY_LOG_PAYLOAD.equals(key)) {
            xmlUnmarshaller.setLogPayload(((boolean) value));
        } else if (UnmarshallerProperties.MOXY_LOGGING_LEVEL.equals(key)) {
            if (value instanceof String) {
                AbstractSessionLog.getLog().setLevel(LogLevel.toValue((String) value).getId(), SessionLog.MOXY);
            } else {
                AbstractSessionLog.getLog().setLevel(((LogLevel) value).getId(), SessionLog.MOXY);
            }
        } else {
            throw new PropertyException(key, value);
        }
    }

    /**
     * Get a property from the JAXBMarshaller. Attempting to get any unsupported
     * property will result in a jakarta.xml.bind.PropertyException
     * See <a href="#supportedProps">Supported Properties</a>.
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties
     */
    @Override
    public Object getProperty(String key) throws PropertyException {
        if (key == null) {
            throw new IllegalArgumentException();
        }
        if (key.equals(UnmarshallerProperties.MEDIA_TYPE)) {
            return xmlUnmarshaller.getMediaType();
        } else if (key.equals(UnmarshallerProperties.AUTO_DETECT_MEDIA_TYPE)) {
            return xmlUnmarshaller.isAutoDetectMediaType();
        } else if (key.equals(UnmarshallerProperties.UNMARSHALLING_CASE_INSENSITIVE)) {
            return xmlUnmarshaller.isCaseInsensitive();
        } else if (key.equals(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX)) {
            return xmlUnmarshaller.getAttributePrefix();
        } else if (key.equals(UnmarshallerProperties.JSON_INCLUDE_ROOT)) {
            return xmlUnmarshaller.isIncludeRoot();
        }  else if (key.equals(UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR)) {
            return xmlUnmarshaller.getNamespaceSeparator();
        } else if (key.equals(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER)) {
            if(xmlUnmarshaller.getNamespaceResolver() == null){
                return null;
            }
            if (xmlUnmarshaller.getNamespaceResolver() instanceof PrefixMapperNamespaceResolver) {
                PrefixMapperNamespaceResolver wrapper = (PrefixMapperNamespaceResolver) xmlUnmarshaller.getNamespaceResolver();
                return wrapper.getPrefixMapper();
            } else {
                Map<String, String> nsMap = new HashMap<String, String>();
                Map<String, String> prefixesToNS = xmlUnmarshaller.getNamespaceResolver().getPrefixesToNamespaces();
                // Reverse the prefixesToNS map
                Iterator<Entry<String, String>> namesapcesIter = prefixesToNS.entrySet().iterator();
                for (int i = 0; i < prefixesToNS.size(); i++) {
                    Entry<String, String> nextEntry = namesapcesIter.next();
                    nsMap.put(nextEntry.getValue(), nextEntry.getKey());
                }
                return nsMap;
            }
        } else if (key.equals(UnmarshallerProperties.JSON_VALUE_WRAPPER)) {
            return xmlUnmarshaller.getValueWrapper();
        } else if (UnmarshallerProperties.JSON_USE_XSD_TYPES_WITH_PREFIX.equals(key)) {
            return xmlUnmarshaller.getJsonTypeConfiguration().isUseXsdTypesWithPrefix();
        } else if (UnmarshallerProperties.JSON_TYPE_COMPATIBILITY.equals(key)) {
            return xmlUnmarshaller.getJsonTypeConfiguration().isJsonTypeCompatibility();
        } else if (MarshallerProperties.JSON_TYPE_ATTRIBUTE_NAME.equals(key)) {
            return xmlUnmarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName();
        } else if (UnmarshallerProperties.ID_RESOLVER.equals(key)) {
            return xmlUnmarshaller.getIDResolver();
        } else if (SUN_ID_RESOLVER.equals(key) || SUN_JSE_ID_RESOLVER.equals(key)) {
            IDResolverWrapper wrapper = (IDResolverWrapper) xmlUnmarshaller.getIDResolver();
            if(wrapper == null){
                return null;
            }
            return wrapper.getResolver();
        } else if (UnmarshallerProperties.OBJECT_GRAPH.equals(key)) {
            Object graph = xmlUnmarshaller.getUnmarshalAttributeGroup();
            if(graph instanceof CoreAttributeGroup) {
                return new ObjectGraphImpl((CoreAttributeGroup)graph);
            }
            return graph;
        } else if(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
            return xmlUnmarshaller.isWrapperAsCollectionName();
        } else if (UnmarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {
            return this.beanValidationMode;
        } else if (UnmarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
            return this.prefValidatorFactory;
        } else if (UnmarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
            return this.beanValidationGroups;
        } else if (UnmarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
            return this.bvNoOptimisation;
        } else if (UnmarshallerProperties.DISABLE_SECURE_PROCESSING.equals(key)) {
            return xmlUnmarshaller.isSecureProcessingDisabled();
        } else if (UnmarshallerProperties.MOXY_LOG_PAYLOAD.equals(key)) {
            return xmlUnmarshaller.isLogPayload();
        }
        throw new PropertyException(key);
    }

    @Override
    public Unmarshaller.Listener getListener() {
        return ((JAXBUnmarshalListener)xmlUnmarshaller.getUnmarshalListener()).getListener();
    }

    @Override
    public void setListener(Unmarshaller.Listener listener) {
        ((JAXBUnmarshalListener)xmlUnmarshaller.getUnmarshalListener()).setListener(listener);
    }

    @Override
    public XmlAdapter getAdapter(Class javaClass) {
        HashMap result = (HashMap) xmlUnmarshaller.getProperty(XML_JAVATYPE_ADAPTERS);
        if (result == null) {
            return null;
        }
        return (XmlAdapter) result.get(javaClass);
    }

    @Override
    public void setAdapter(Class javaClass, XmlAdapter adapter) {
        HashMap result = (HashMap) xmlUnmarshaller.getProperty(XML_JAVATYPE_ADAPTERS);
        if (result == null) {
            result = new HashMap();
            xmlUnmarshaller.getProperties().put(XML_JAVATYPE_ADAPTERS, result);
        }
        result.put(javaClass, adapter);
    }

    @Override
    public void setAdapter(XmlAdapter adapter) {
        setAdapter(adapter.getClass(), adapter);
    }

    @Override
    public void setSchema(Schema schema) {
        this.xmlUnmarshaller.setSchema(schema);
    }

    @Override
    public Schema getSchema() {
        return this.xmlUnmarshaller.getSchema();
    }

    @Override
    public AttachmentUnmarshaller getAttachmentUnmarshaller() {
        if(xmlUnmarshaller.getAttachmentUnmarshaller() == null) {
            return null;
        }
        return ((AttachmentUnmarshallerAdapter)xmlUnmarshaller.getAttachmentUnmarshaller()).getAttachmentUnmarshaller();
    }

    @Override
    public void setAttachmentUnmarshaller(AttachmentUnmarshaller unmarshaller) {
        if(unmarshaller == null) {
            xmlUnmarshaller.setAttachmentUnmarshaller(null);
        } else {
            xmlUnmarshaller.setAttachmentUnmarshaller(new AttachmentUnmarshallerAdapter(unmarshaller));
        }
    }

    public void setUnmarshalCallbacks(Map callbacks) {
        ((JAXBUnmarshalListener)xmlUnmarshaller.getUnmarshalListener()).setClassBasedUnmarshalEvents(callbacks);
    }

    private Object validateAndTransformIfRequired(Object obj) throws BeanValidationException {
        if (beanValidator != null && beanValidator.shouldValidate(obj, beanValidationMode, prefValidatorFactory, bvNoOptimisation)) {
            beanValidator.validate(obj, beanValidationGroups);
        }
        return createJAXBElementOrUnwrapIfRequired(obj);
    }

    private Object createJAXBElementOrUnwrapIfRequired(Object value) {
        if(value instanceof Root){
            JAXBElement jaxbElement = jaxbContext.createJAXBElementFromXMLRoot((Root)value, Object.class);
            jaxbElement.setNil(((Root) value).isNil());
            return jaxbElement;
        } else if(value instanceof WrappedValue) {
            return ((WrappedValue)value).getValue();
        }
        return value;
    }


    public JAXBContext getJaxbContext() {
        return jaxbContext;
    }

    private Class getClassToUnmarshalTo(Class originalClass) {
        Class classToUnmarshalTo = originalClass;
        if(jaxbContext.getArrayClassesToGeneratedClasses() != null && jaxbContext.getArrayClassesToGeneratedClasses().size() >0) {
            Class generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(originalClass.getCanonicalName());
            if(generatedClass != null){
                classToUnmarshalTo = generatedClass;
            }
        }
        if(jaxbContext.getCollectionClassesToGeneratedClasses() != null && jaxbContext.getCollectionClassesToGeneratedClasses().size() >0){
            Class generatedClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(originalClass);
            if(generatedClass != null){
                classToUnmarshalTo = generatedClass;
            }
        }
        if(jaxbContext.getTypeToTypeMappingInfo() != null){
            TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(originalClass);
            if(tmi != null && jaxbContext.getTypeMappingInfoToGeneratedType() != null) {
                Class generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);
                if(generatedClass != null){
                    classToUnmarshalTo = generatedClass;
                }
            }
        }
        return classToUnmarshalTo;
    }

    private JAXBException handleXMLMarshalException(XMLMarshalException xmlMarshalException) {
        if(xmlMarshalException.getErrorCode() == XMLMarshalException.NULL_ARGUMENT) {
            throw new IllegalArgumentException(xmlMarshalException);
        } else {
            return new UnmarshalException(xmlMarshalException);
        }
    }


    /**
     * Return this Unmarshaller's custom IDResolver.
     *
     * @see IDResolver
     * @since 2.3.3
     * @return the custom IDResolver, or null if one has not been specified.
     */
    public IDResolver getIDResolver() {
        return getXMLUnmarshaller().getIDResolver();
    }

    /**
     * Set this Unmarshaller's custom IDResolver.
     *
     * @see IDResolver
     * @since 2.3.3
     */
    public void setIDResolver(IDResolver idResolver) {
        getXMLUnmarshaller().setIDResolver(idResolver);
    }

    /**
     * Returns constraint violations stored in the underlying
     * {@link org.eclipse.persistence.jaxb.JAXBBeanValidator} instance.
     *
     * @return set of constraint violations from last unmarshal
     */
    public Set<ConstraintViolationWrapper<Object>> getConstraintViolations() {
        if (beanValidator != null) {
            return beanValidator.getConstraintViolations();
        }
        return Collections.emptySet();
    }

    private static class PrimitiveContentHandler<T> extends DefaultHandler {

        private Class<T> clazz;
        private JAXBElement<T> jaxbElement;
        private Map<String, String> namespaces = new HashMap<String, String>(3);
        private StringBuilder stringBuilder = new StringBuilder();
        private String xsiType;
        private boolean xsiNil;

        public PrimitiveContentHandler(Class<T> clazz) {
            this.clazz = clazz;
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            stringBuilder.append(ch, start, length);
        }

        @Override
        public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException {
            XMLConversionManager xcm = XMLConversionManager.getDefaultXMLManager();
            T value;
            if(xsiNil) {
                value = null;
            } else if(null == xsiType) {
                if (clazz == CoreClassConstants.ABYTE || clazz == CoreClassConstants.APBYTE || clazz.getCanonicalName().equals("jakarta.activation.DataHandler")) {
                    value = xcm.convertObject(stringBuilder.toString(), clazz, Constants.BASE_64_BINARY_QNAME);
                } else {
                    value = xcm.convertObject(stringBuilder.toString(), clazz);
                }
            } else {
                int colonIndex = xsiType.indexOf(':');

                String typePrefix;
                String typeName;
                if(colonIndex == -1) {
                    typePrefix = Constants.EMPTY_STRING;
                    typeName = xsiType;
                } else {
                    typePrefix = xsiType.substring(0, colonIndex);
                    typeName = xsiType.substring(colonIndex + 1);
                }
                String typeNamespace = namespaces.get(typePrefix);
                QName typeQName = new QName(typeNamespace, typeName);
                value = xcm.convertObject(stringBuilder.toString(), clazz, typeQName);

            }

            QName qName;
            if(namespaceURI != null && namespaceURI.length() == 0) {
                qName = new QName(qualifiedName);
            } else {
                qName = new QName(namespaceURI, localName);
            }
            jaxbElement = new JAXBElement<T>(qName, clazz, value);
        }

        public JAXBElement<T> getJaxbElement() {
            return jaxbElement;
        }

        @Override
        public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException {
            String xsiNilValue = attributes.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE);
            if (xsiNilValue != null) {
                xsiNil = xsiNilValue.equals(Constants.BOOLEAN_STRING_TRUE) || xsiNilValue.equals("1");
            }

            if (!xsiNil) {
                xsiType = attributes.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_TYPE_ATTRIBUTE);
            }
        }

        @Override
        public void startPrefixMapping(String prefix, String uri)
                throws SAXException {
            namespaces.put(prefix, uri);
        }

    }

    private static class PrimitiveArrayContentHandler<T, E> extends DefaultHandler {

        private Class<T> arrayClass;
        private Class<E> componentClass;
        private JAXBElement<T> jaxbElement;

        private QName qName;

        private StrBuffer stringBuffer = new StrBuffer();

        private boolean xsiNil;
        private boolean singleNode;
        private boolean acceptCharacters = false;

        private T unmarshalledArray;
        private int currentIndex = 0;
        private int currentSize = 10; // INITIAL SIZE

        private XMLConversionManager xcm = XMLConversionManager.getDefaultXMLManager();

        public PrimitiveArrayContentHandler(Class<T> arrayClass, Class<E> componentClass, boolean usesSingleNode) {
            this.arrayClass = arrayClass;
            this.componentClass = componentClass;
            this.singleNode = usesSingleNode;
            this.unmarshalledArray = (T) Array.newInstance(componentClass, currentSize);
        }

        @Override
        public void startElement(String namespaceURI, String localName, String qualifiedName, Attributes attributes) throws SAXException {
            if (localName.equals("item") || singleNode) {
                acceptCharacters = true;
            }

            String xsiNilValue = attributes.getValue(javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, Constants.SCHEMA_NIL_ATTRIBUTE);
            if (xsiNilValue != null) {
                xsiNil = xsiNilValue.equals(Constants.BOOLEAN_STRING_TRUE) || xsiNilValue.equals("1");
            }
        }

        @Override
        public void characters(char[] ch, int start, int length) throws SAXException {
            if (acceptCharacters) {
                stringBuffer.append(ch, start, length);
            }
        }

        @Override
        public void endElement(String namespaceURI, String localName, String qualifiedName) throws SAXException {
            acceptCharacters = false;

            if (!qualifiedName.equals("item")) {
                if (namespaceURI != null && namespaceURI.length() == 0) {
                    qName = new QName(qualifiedName);
                } else {
                    qName = new QName(namespaceURI, localName);
                }
                if (!singleNode) {
                    return;
                }
            }

            if (singleNode) {
                endElementSingleNode();
                return;
            }

            E value;

            if (xsiNil) {
                value = null;
            } else {
                value = xcm.convertObject(stringBuffer.toString(), componentClass);
            }
            addValue(value);
            stringBuffer.reset();
        }

        private void endElementSingleNode() {
            acceptCharacters = false;

            E value;

            if (xsiNil) {
                addValue(null);
                stringBuffer.reset();
                return;
            }

            StringTokenizer st = new StringTokenizer(stringBuffer.toString());

            while (st.hasMoreTokens()) {
                String nextToken = st.nextToken();
                value = xcm.convertObject(nextToken, componentClass);
                addValue(value);
            }
            stringBuffer.reset();
        }

        private void addValue(E value) {
            if (currentIndex == currentSize) {
                growArray();
            }
            Array.set(unmarshalledArray, currentIndex, value);
            currentIndex++;
        }

        private void growArray() {
            int newSize = currentSize * 2;
            T newArray = (T) Array.newInstance(componentClass, newSize);
            System.arraycopy(unmarshalledArray, 0, newArray, 0, currentSize);
            unmarshalledArray = newArray;
            currentSize = newSize;
        }

        public JAXBElement<T> getJaxbElement() {
            if (null == jaxbElement) {
                // "trim" array
                T newArray = (T) Array.newInstance(componentClass, currentIndex);
                System.arraycopy(unmarshalledArray, 0, newArray, 0, currentIndex);

                jaxbElement = new JAXBElement<T>(qName, arrayClass, newArray);
            }
            return jaxbElement;
        }
    }
}
