/*
 * 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.FileOutputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.MarshalException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.PropertyException;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import jakarta.xml.bind.attachment.AttachmentMarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventWriter;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Result;
import javax.xml.validation.Schema;

import org.eclipse.persistence.core.queries.CoreAttributeGroup;
import org.eclipse.persistence.descriptors.ClassDescriptor;
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.helper.ClassConstants;
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.localization.JAXBLocalization;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.oxm.Root;
import org.eclipse.persistence.internal.oxm.record.namespaces.MapNamespacePrefixMapper;
import org.eclipse.persistence.internal.oxm.record.namespaces.NamespacePrefixMapperWrapper;
import org.eclipse.persistence.jaxb.JAXBContext.RootLevelXmlAdapter;
import org.eclipse.persistence.jaxb.attachment.AttachmentMarshallerAdapter;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.LogLevel;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.CharacterEscapeHandler;
import org.eclipse.persistence.oxm.JSONWithPadding;
import org.eclipse.persistence.oxm.MediaType;
import org.eclipse.persistence.oxm.NamespacePrefixMapper;
import org.eclipse.persistence.oxm.XMLMarshalListener;
import org.eclipse.persistence.oxm.XMLMarshaller;
import org.eclipse.persistence.oxm.record.MarshalRecord;
import org.eclipse.persistence.oxm.record.XMLEventWriterRecord;
import org.eclipse.persistence.oxm.record.XMLStreamWriterRecord;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;

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

public class JAXBMarshaller implements jakarta.xml.bind.Marshaller {

    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 XMLMarshaller xmlMarshaller;
    private final JAXBContext jaxbContext;
    private ValidationEventHandler validationEventHandler;

    public static final String XML_JAVATYPE_ADAPTERS = "xml-javatype-adapters";

    private static final String SUN_NAMESPACE_PREFIX_MAPPER = "org.glassfish.jaxb.namespacePrefixMapper";
    private static final String SUN_JSE_NAMESPACE_PREFIX_MAPPER = "com.sun.xml.internal.bind.namespacePrefixMapper";

    private static final String SUN_INDENT_STRING = "org.glassfish.jaxb.indentString";
    private static final String SUN_JSE_INDENT_STRING = "com.sun.xml.internal.bind.indentString";

    private static final String SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "org.glassfish.jaxb.marshaller.CharacterEscapeHandler";
    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER = "com.sun.xml.internal.bind.marshaller.CharacterEscapeHandler";

    private static final String SUN_CHARACTER_ESCAPE_HANDLER= "org.glassfish.jaxb.characterEscapeHandler";
    private static final String SUN_JSE_CHARACTER_ESCAPE_HANDLER = "com.sun.xml.internal.bind.characterEscapeHandler";

    // XML_DECLARATION is the "opposite" to JAXB_FRAGMENT.  If XML_DECLARATION is set to false it means JAXB_FRAGMENT should be set to true.
    private static final String XML_DECLARATION = "org.glassfish.jaxb.xmlDeclaration";

    private static final String XML_HEADERS = "org.glassfish.jaxb.xmlHeaders";

    private static final String OBJECT_IDENTITY_CYCLE_DETECTION = "org.glassfish.jaxb.objectIdentitityCycleDetection";

    /**
     * This constructor initializes various settings on the XML marshaller.
     *
     * @param newXMLMarshaller xml marshaller
     * @param jaxbContext jaxb context
     */
    public JAXBMarshaller(XMLMarshaller newXMLMarshaller, JAXBContext jaxbContext) {
        this.jaxbContext = jaxbContext;
        validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
        beanValidationMode = BeanValidationMode.AUTO;
        if (BeanValidationChecker.isBeanValidationPresent()) {
            beanValidator = JAXBBeanValidator.getMarshallingBeanValidator(jaxbContext);
        }
        xmlMarshaller = newXMLMarshaller;
        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
        xmlMarshaller.setEncoding("UTF-8");
        xmlMarshaller.setFormattedOutput(false);
        xmlMarshaller.getProperties().put(Constants.JAXB_MARSHALLER, this);
    }

    /**
     * Create an instance of XMLRoot populated from the contents of the provided
     * JAXBElement. XMLRoot will be used to hold the contents of the JAXBElement
     * while the marshal operation is performed by TopLink OXM. This will avoid
     * adding any runtime dependencies to TopLink.
     *
     */
    private Root createXMLRootFromJAXBElement(JAXBElement elt) {
        // create an XMLRoot to hand into the marshaller
        Root xmlroot = new Root();
        Object objectValue = elt.getValue();
        xmlroot.setObject(objectValue);
        QName qname = elt.getName();
        xmlroot.setLocalName(qname.getLocalPart());
        xmlroot.setNamespaceURI(qname.getNamespaceURI());
        xmlroot.setDeclaredType(elt.getDeclaredType());
        xmlroot.setNil(elt.isNil());
        if (elt.getDeclaredType() == CoreClassConstants.ABYTE || elt.getDeclaredType() == CoreClassConstants.APBYTE ||
                elt.getDeclaredType().getCanonicalName().equals("jakarta.activation.DataHandler") ||
                elt.getDeclaredType().isEnum()) {
            // need a binary data mapping so need to wrap
            Class generatedClass = getClassToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());
            if(!elt.getDeclaredType().isEnum()) {
                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);
            }
            if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
                ((WrappedValue) newObject).setValue(objectValue);
                xmlroot.setObject(newObject);
                return xmlroot;
            }
        } else {
            xmlroot.setSchemaType(org.eclipse.persistence.internal.oxm.XMLConversionManager.getDefaultJavaTypes().get(elt.getDeclaredType()));
        }

        if (elt instanceof WrappedValue) {
            xmlroot.setObject(elt);
            return xmlroot;
        }
        Map<QName, Class> qNameToGeneratedClasses = jaxbContext.getQNameToGeneratedClasses();
        if (qNameToGeneratedClasses != null) {
            Class theClass = qNameToGeneratedClasses.get(qname);
            if (theClass != null && WrappedValue.class.isAssignableFrom(theClass)) {
                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(theClass).getDescriptor(theClass);
                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
                ((WrappedValue) newObject).setValue(objectValue);
                xmlroot.setObject(newObject);
                return xmlroot;
            }
        }

        Class generatedClass = null;
        if (jaxbContext.getTypeMappingInfoToGeneratedType() != null) {
            if (jaxbContext.getTypeToTypeMappingInfo() != null) {
                if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {
                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(elt.getDeclaredType());
                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);
                } else if (elt instanceof JAXBTypeElement) {
                    Type objectType = ((JAXBTypeElement) elt).getType();
                    TypeMappingInfo tmi = jaxbContext.getTypeToTypeMappingInfo().get(objectType);
                    generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(tmi);
                }
            }
        } else {
            if (elt.getDeclaredType() != null && elt.getDeclaredType().isArray()) {
                if (jaxbContext.getArrayClassesToGeneratedClasses() != null) {
                    generatedClass = jaxbContext.getArrayClassesToGeneratedClasses().get(elt.getDeclaredType().getCanonicalName());
                }
            } else if (elt instanceof JAXBTypeElement) {
                Type objectType = ((JAXBTypeElement) elt).getType();
                generatedClass = jaxbContext.getCollectionClassesToGeneratedClasses().get(objectType);
            }
        }

        if (generatedClass != null) {
            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
            Object newObject = desc.getInstantiationPolicy().buildNewInstance();
            ((ManyValue) newObject).setItem(objectValue);
            xmlroot.setObject(newObject);
        }

        return xmlroot;
    }

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

    @Override
    public AttachmentMarshaller getAttachmentMarshaller() {
        if (xmlMarshaller.getAttachmentMarshaller() == null) {
            return null;
        }
        return ((AttachmentMarshallerAdapter) xmlMarshaller.getAttachmentMarshaller()).getAttachmentMarshaller();
    }

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

    @Override
    public Marshaller.Listener getListener() {
        XMLMarshalListener xmlMarshalListener = xmlMarshaller.getMarshalListener();
        if(null != xmlMarshalListener) {
            return ((JAXBMarshalListener) xmlMarshalListener).getListener();
        }
        return null;
    }

    @Override
    public Node getNode(Object object) throws JAXBException {
        throw new UnsupportedOperationException();
    }

    /**
     * Get a property from the JAXBMarshaller. Attempting to get any unsupported
     * property will result in a jakarta.xml.bind.PropertyException
     * @see org.eclipse.persistence.jaxb.MarshallerProperties
     */
    @Override
    public Object getProperty(String key) throws PropertyException {
        if (key == null) {
            throw new IllegalArgumentException();
        } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {
            return xmlMarshaller.isFormattedOutput();
        } else if (JAXB_ENCODING.equals(key)) {
            return xmlMarshaller.getEncoding();
        } else if (JAXB_SCHEMA_LOCATION.equals(key)) {
            return xmlMarshaller.getSchemaLocation();
        } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {
            return xmlMarshaller.getNoNamespaceSchemaLocation();
        } else if (Constants.JAXB_FRAGMENT.equals(key)) {
            return xmlMarshaller.isFragment();
        } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {
            return xmlMarshaller.getMediaType();
        } else if (MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) {
            return xmlMarshaller.getNamespacePrefixMapper();
        } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {
            return xmlMarshaller.getIndentString();
        } else if (MarshallerProperties.CHARACTER_ESCAPE_HANDLER.equals(key)) {
            return xmlMarshaller.getCharacterEscapeHandler();
        } else if (XML_DECLARATION.equals(key)) {
            return !xmlMarshaller.isFragment();
        } else if (XML_HEADERS.equals(key)) {
            return xmlMarshaller.getXmlHeader();
        } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {
            return xmlMarshaller.isEqualUsingIdenity();
        } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {
            return xmlMarshaller.getAttributePrefix();
        } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {
            return xmlMarshaller.isIncludeRoot();
        } else if (MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)) {
            return xmlMarshaller.getValueWrapper();
        } else if (MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)) {
            return xmlMarshaller.getNamespaceSeparator();
        } else if (MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
            return xmlMarshaller.isWrapperAsCollectionName();
        } else if (MarshallerProperties.JSON_USE_XSD_TYPES_WITH_PREFIX.equals(key)) {
            return xmlMarshaller.getJsonTypeConfiguration().isUseXsdTypesWithPrefix();
        } else if (MarshallerProperties.JSON_TYPE_COMPATIBILITY.equals(key)) {
            return xmlMarshaller.getJsonTypeConfiguration().isJsonTypeCompatibility();
        } else if (MarshallerProperties.JSON_TYPE_ATTRIBUTE_NAME.equals(key)) {
            return xmlMarshaller.getJsonTypeConfiguration().getJsonTypeAttributeName();
        } else if (MarshallerProperties.JSON_DISABLE_NESTED_ARRAY_NAME.equals(key)) {
            return xmlMarshaller.getJsonTypeConfiguration().isJsonDisableNestedArrayName();
        } else if (SUN_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER.equals(key) ||SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key)) {
            if (xmlMarshaller.getCharacterEscapeHandler() instanceof CharacterEscapeHandlerWrapper) {
                CharacterEscapeHandlerWrapper wrapper = (CharacterEscapeHandlerWrapper) xmlMarshaller.getCharacterEscapeHandler();
                return wrapper.getHandler();
            }
            return xmlMarshaller.getCharacterEscapeHandler();
        } else if (SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {
            NamespacePrefixMapperWrapper wrapper = (NamespacePrefixMapperWrapper) xmlMarshaller.getNamespacePrefixMapper();
            if(wrapper == null){
                return null;
            }
            return wrapper.getPrefixMapper();
        } else if (MarshallerProperties.OBJECT_GRAPH.equals(key)) {
            Object graph = xmlMarshaller.getMarshalAttributeGroup();
            if(graph instanceof CoreAttributeGroup) {
                return new ObjectGraphImpl((CoreAttributeGroup)graph);
            }
            return graph;
        } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {
            return this.beanValidationMode;
        } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
            return this.prefValidatorFactory;
        } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
            return this.beanValidationGroups;
        } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
            return this.bvNoOptimisation;
        } else if (MarshallerProperties.MOXY_LOG_PAYLOAD.equals(key)) {
            return xmlMarshaller.isLogPayload();
        }
        throw new PropertyException(key);
    }

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

    @Override
    public void marshal(Object object, ContentHandler contentHandler) throws JAXBException {
        if (object == null || contentHandler == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            xmlMarshaller.marshal(oxmObject, contentHandler);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

    private Object wrapEnumeration(Object object, Class enumerationClass) {
        Class generatedClass = this.getClassToGeneratedClasses().get(enumerationClass.getName());
        if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
            ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
            Object newObject = desc.getInstantiationPolicy().buildNewInstance();
            ((WrappedValue) newObject).setValue(object);
            object = newObject;
        }
        return object;
    }

    @Override
    public void marshal(Object object, XMLEventWriter eventWriter) throws JAXBException {
        if (object == null || eventWriter == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            XMLEventWriterRecord record = new XMLEventWriterRecord(eventWriter);
            record.setMarshaller(this.xmlMarshaller);
            this.xmlMarshaller.marshal(oxmObject, record);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception ex) {
            throw new MarshalException(ex);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

    public void marshal(Object object, XMLEventWriter eventWriter, TypeMappingInfo type) throws JAXBException {
        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
            marshal(object, eventWriter);
        } else {
            JAXBElement element = null;
            Object value = object;
            if (object instanceof JAXBElement) {
                // use the JAXBElement's properties to populate an XMLRoot
                element = (JAXBElement) object;
                value = element.getValue();
            }

            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
            if (adapter != null) {
                try {
                    value = adapter.getXmlAdapter().marshal(value);
                } catch (Exception ex) {
                    throw new JAXBException(XMLMarshalException.marshalException(ex));
                }
            }

            value = wrapObject(value, element, type);
            marshal(value, eventWriter);
        }
    }

    @Override
    public void marshal(Object object, Node node) throws JAXBException {
        if (object == null || node == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            xmlMarshaller.marshal(oxmObject, node);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

    @Override
    public void marshal(Object object, OutputStream outputStream) throws JAXBException {
        if (object == null || outputStream == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            xmlMarshaller.marshal(oxmObject, outputStream);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

    @Override
    public void marshal(Object object, File file) throws JAXBException {
        try {
            FileOutputStream outputStream = new FileOutputStream(file);
            try {
                marshal(object, outputStream); // link to the other one
            } finally {
                outputStream.close();
            }
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception ex) {
            throw new MarshalException(ex);
        }
    }

    @Override
    public void marshal(Object object, Result result) throws JAXBException {
        if (object == null || result == null) {
            throw new IllegalArgumentException();
        }
        object = validateAndTransformIfNeeded(object); // xml bindings + json object

        try {
            xmlMarshaller.marshal(object, result);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }
    }

    public void marshal(Object object, Result result, TypeMappingInfo type) throws JAXBException {
        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
            marshal(object, result);
        } else {
            JAXBElement element = null;
            Object value = object;
            if (object instanceof JAXBElement) {
                // use the JAXBElement's properties to populate an XMLRoot
                element = (JAXBElement) object;
                value = element.getValue();
            }

            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){
                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);

                if (adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().marshal(value);
                    } catch (Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
            }
            value = wrapObject(value, element, type);
            marshal(value, result);
        }
    }

    @Override
    public void marshal(Object object, XMLStreamWriter streamWriter) throws JAXBException {
        if (object == null || streamWriter == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            XMLStreamWriterRecord record = new XMLStreamWriterRecord(streamWriter);
            record.setMarshaller(this.xmlMarshaller);
            this.xmlMarshaller.marshal(oxmObject, record);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception ex) {
            throw new MarshalException(ex);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

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

    private Object modifyObjectIfNeeded(Object obj) {
        if (obj instanceof Collection) {
            Collection objectList = (Collection) obj;
            List newList = new ArrayList(objectList.size());
            for (Object o : objectList) {
                newList.add(modifySingleObjectIfNeeded(o));
            }
            return newList;
        } else if (obj.getClass().isArray()) {
            int arraySize = Array.getLength(obj);
            List newList = new ArrayList(arraySize);
            for (int x = 0; x < arraySize; x++) {
                newList.add(modifySingleObjectIfNeeded(Array.get(obj, x)));
            }
            return newList;
        } else {
            return modifySingleObjectIfNeeded(obj);
        }
    }

    private Object modifySingleObjectIfNeeded(Object obj){
    // let the JAXBIntrospector determine if the object is a JAXBElement
        if (obj instanceof JAXBElement) {
            // use the JAXBElement's properties to populate an XMLRoot
            return createXMLRootFromJAXBElement((JAXBElement) obj);
        } else if(obj != null && obj.getClass().isEnum()) {
            return wrapEnumeration(obj, obj.getClass());
        } else if (obj instanceof JSONWithPadding){
            Object nestedObject = ((JSONWithPadding)obj).getObject();
            if(nestedObject != null){
                Object newNestedObject = modifyObjectIfNeeded(nestedObject);
                if(nestedObject != newNestedObject){
                    return new JSONWithPadding(newNestedObject,((JSONWithPadding)obj).getCallbackName());
                }
            }
        }
        return obj;
    }

    public void marshal(Object object, XMLStreamWriter streamWriter, TypeMappingInfo type) throws JAXBException {
        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
            marshal(object, streamWriter);
        } else {
            JAXBElement element = null;
            Object value = object;
            if (object instanceof JAXBElement) {
                // use the JAXBElement's properties to populate an XMLRoot
                element = (JAXBElement) object;
                value = element.getValue();
            }
            if(jaxbContext.getTypeMappingInfoToJavaTypeAdapters().size() > 0){
                RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
                if (adapter != null) {
                    try {
                        value = adapter.getXmlAdapter().marshal(value);
                    } catch (Exception ex) {
                        throw new JAXBException(XMLMarshalException.marshalException(ex));
                    }
                }
            }

            value = wrapObject(value, element, type);
            marshal(value, streamWriter);
        }
    }

    private Object wrapObject(Object object, JAXBElement wrapperElement, TypeMappingInfo typeMappingInfo) {
        if(jaxbContext.getTypeMappingInfoToGeneratedType().size() > 0){
            Class generatedClass = jaxbContext.getTypeMappingInfoToGeneratedType().get(typeMappingInfo);
            if(generatedClass != null && object == null && wrapperElement != null) {
            return wrapObjectInXMLRoot(wrapperElement, null, typeMappingInfo);
            }

            if (generatedClass != null && WrappedValue.class.isAssignableFrom(generatedClass)) {
                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
                ((WrappedValue) newObject).setValue(object);
                object = newObject;
            } else if (generatedClass != null) {
                // should be a many value
                ClassDescriptor desc = xmlMarshaller.getXMLContext().getSession(generatedClass).getDescriptor(generatedClass);
                Object newObject = desc.getInstantiationPolicy().buildNewInstance();
                ((ManyValue) newObject).setItem(object);
                object = newObject;
            }
        }

        if (null == wrapperElement) {
            Root xmlRoot = new Root();
            QName xmlTagName = typeMappingInfo.getXmlTagName();
            if (null == xmlTagName) {
                return object;
            }
            xmlRoot.setNamespaceURI(typeMappingInfo.getXmlTagName().getNamespaceURI());
            xmlRoot.setLocalName(typeMappingInfo.getXmlTagName().getLocalPart());
            xmlRoot.setObject(object);
            return xmlRoot;

        }
        return wrapObjectInXMLRoot(wrapperElement, object, typeMappingInfo);
    }

    private Root wrapObjectInXMLRoot(JAXBElement wrapperElement, Object value, TypeMappingInfo typeMappingInfo) {
        Root xmlroot = new Root();
        Object objectValue = value;
        xmlroot.setObject(objectValue);
        QName qname = wrapperElement.getName();
        xmlroot.setLocalName(qname.getLocalPart());
        xmlroot.setNamespaceURI(qname.getNamespaceURI());
        xmlroot.setDeclaredType(wrapperElement.getDeclaredType());
        if(typeMappingInfo != null){
            xmlroot.setSchemaType(typeMappingInfo.getSchemaType());
        } else if(value != null) {
            if (value.getClass() == CoreClassConstants.ABYTE || value.getClass() == CoreClassConstants.APBYTE ||
                    value.getClass().getCanonicalName().equals("jakarta.activation.DataHandler")) {
                xmlroot.setSchemaType(Constants.BASE_64_BINARY_QNAME);
            }
        }
        return xmlroot;
    }

    @Override
    public void marshal(Object object, Writer writer) throws JAXBException {
        if (object == null || writer == null) {
            throw new IllegalArgumentException();
        }

        Listener listener = getListener();
        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.beforeMarshal(object);
            }
        }

        Object oxmObject = validateAndTransformIfNeeded(object); // xml bindings + object
        try {
            xmlMarshaller.marshal(oxmObject, writer);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }

        if(listener != null) {
            if(object instanceof JAXBElement) {
                listener.afterMarshal(object);
            }
        }
    }

    public void marshal(Object object, MarshalRecord record) throws JAXBException {
        if (object == null || record == null) {
            throw new IllegalArgumentException();
        }
        object = validateAndTransformIfNeeded(object); // xml bindings + object

        try {
            record.setMarshaller(xmlMarshaller);
            xmlMarshaller.marshal(object, record);
        } catch (BeanValidationException bve) {
            throw new MarshalException(bve.getMessage(), String.valueOf(bve.getErrorCode()), bve);
        } catch (Exception e) {
            throw new MarshalException(e);
        }
    }

    public void marshal(Object object, MarshalRecord record, TypeMappingInfo type) throws JAXBException {
        if (jaxbContext.getTypeMappingInfoToGeneratedType() == null) {
            marshal(object, record);
        } else {
            JAXBElement element = null;
            Object value = object;
            if (object instanceof JAXBElement) {
                // use the JAXBElement's properties to populate an XMLRoot
                element = (JAXBElement) object;
                value = element.getValue();
            }
            RootLevelXmlAdapter adapter = jaxbContext.getTypeMappingInfoToJavaTypeAdapters().get(type);
            if (adapter != null) {
                try {
                    value = adapter.getXmlAdapter().marshal(value);
                } catch (Exception ex) {
                    throw new JAXBException(XMLMarshalException.marshalException(ex));
                }
            }
            value = wrapObject(value, element, type);
            marshal(value, record);
        }
    }

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

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

    @Override
    public void setAttachmentMarshaller(AttachmentMarshaller attachmentMarshaller) {
        if (attachmentMarshaller == null) {
            xmlMarshaller.setAttachmentMarshaller(null);
        } else {
            xmlMarshaller.setAttachmentMarshaller(new AttachmentMarshallerAdapter(attachmentMarshaller));
        }
    }

    @Override
    public void setEventHandler(ValidationEventHandler newValidationEventHandler) throws JAXBException {
        if (null == newValidationEventHandler) {
            validationEventHandler = JAXBContext.DEFAULT_VALIDATION_EVENT_HANDLER;
        } else {
            validationEventHandler = newValidationEventHandler;
        }
        xmlMarshaller.setErrorHandler(new JAXBErrorHandler(validationEventHandler));
    }

    @Override
    public void setListener(Marshaller.Listener listener) {
        if(xmlMarshaller.getMarshalListener() == null) {
            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));
        }
        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setListener(listener);
    }

    public void setMarshalCallbacks(Map callbacks) {
        if(callbacks == null || callbacks.isEmpty()) {
            return;
        }
        if(xmlMarshaller.getMarshalListener() == null) {
            xmlMarshaller.setMarshalListener(new JAXBMarshalListener(jaxbContext, this));
        }
        ((JAXBMarshalListener) xmlMarshaller.getMarshalListener()).setClassBasedMarshalEvents(callbacks);
    }

    /**
     * Set a property on the JAXBMarshaller. Attempting to set any unsupported
     * property will result in a jakarta.xml.bind.PropertyException
     * @see org.eclipse.persistence.jaxb.MarshallerProperties
     */
    @Override
    public void setProperty(String key, Object value) throws PropertyException {
        try {
            if (key == null) {
                throw new IllegalArgumentException();
            } else {
                SessionLog logger = AbstractSessionLog.getLog();
                if (logger.shouldLog(SessionLog.FINE, SessionLog.MOXY)) {
                    logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_set_marshaller_property", new Object[] {key, value});
                }
                if (MOXySystemProperties.moxyLogPayload != null && xmlMarshaller.isLogPayload() == null) {
                    xmlMarshaller.setLogPayload(MOXySystemProperties.moxyLogPayload);
                }
                if (Constants.JAXB_FRAGMENT.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    Boolean fragment = (Boolean) value;
                    xmlMarshaller.setFragment(fragment);
                } else if (JAXB_FORMATTED_OUTPUT.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    Boolean formattedOutput = (Boolean) value;
                    xmlMarshaller.setFormattedOutput(formattedOutput);
                } else if (JAXB_ENCODING.equals(key)) {
                    xmlMarshaller.setEncoding((String) value);
                } else if (JAXB_SCHEMA_LOCATION.equals(key)) {
                    xmlMarshaller.setSchemaLocation((String) value);
                } else if (JAXB_NO_NAMESPACE_SCHEMA_LOCATION.equals(key)) {
                    xmlMarshaller.setNoNamespaceSchemaLocation((String) value);
                } else if (MarshallerProperties.NAMESPACE_PREFIX_MAPPER.equals(key)) {
                    if (value == null) {
                        xmlMarshaller.setNamespacePrefixMapper(null);
                    } else if (value instanceof Map) {
                        NamespacePrefixMapper namespacePrefixMapper = new MapNamespacePrefixMapper((Map) value);
                        xmlMarshaller.setNamespacePrefixMapper(namespacePrefixMapper);
                    } else {
                        xmlMarshaller.setNamespacePrefixMapper((NamespacePrefixMapper) value);
                    }
                } else if (SUN_NAMESPACE_PREFIX_MAPPER.equals(key) || SUN_JSE_NAMESPACE_PREFIX_MAPPER.equals(key)) {
                    if (value == null) {
                        xmlMarshaller.setNamespacePrefixMapper(null);
                    } else {
                        xmlMarshaller.setNamespacePrefixMapper(new NamespacePrefixMapperWrapper(value));
                    }
                } else if (MarshallerProperties.INDENT_STRING.equals(key) || SUN_INDENT_STRING.equals(key) || SUN_JSE_INDENT_STRING.equals(key)) {
                    xmlMarshaller.setIndentString((String) value);
                } else if (MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS.equals(key)) {
                    xmlMarshaller.setMarshalEmptyCollections((Boolean) value);
                } else if (MarshallerProperties.JSON_REDUCE_ANY_ARRAYS.equals(key)) {
                    xmlMarshaller.setReduceAnyArrays((Boolean) value);
                } else if (MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME.equals(key)) {
                    xmlMarshaller.setWrapperAsCollectionName((Boolean) value);
                } else if (MarshallerProperties.JSON_USE_XSD_TYPES_WITH_PREFIX.equals(key)) {
                    xmlMarshaller.getJsonTypeConfiguration().setUseXsdTypesWithPrefix((Boolean) value);
                } else if (MarshallerProperties.JSON_TYPE_COMPATIBILITY.equals(key)) {
                    xmlMarshaller.getJsonTypeConfiguration().setJsonTypeCompatibility((Boolean) value);
                } else if (MarshallerProperties.JSON_TYPE_ATTRIBUTE_NAME.equals(key)) {
                    xmlMarshaller.getJsonTypeConfiguration().setJsonTypeAttributeName((String) value);
                } else if (MarshallerProperties.JSON_DISABLE_NESTED_ARRAY_NAME.equals(key)) {
                    xmlMarshaller.getJsonTypeConfiguration().setJsonDisableNestedArrayName((Boolean) value);
                } else if (MarshallerProperties.CHARACTER_ESCAPE_HANDLER.equals(key)) {
                    xmlMarshaller.setCharacterEscapeHandler((CharacterEscapeHandler) value);
                } else if (MarshallerProperties.MOXY_LOG_PAYLOAD.equals(key)) {
                    xmlMarshaller.setLogPayload(((Boolean) value));
                } else if (MarshallerProperties.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 if (SUN_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER.equals(key) || SUN_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key) || SUN_JSE_CHARACTER_ESCAPE_HANDLER_MARSHALLER.equals(key)) {
                    if (value == null) {
                        xmlMarshaller.setCharacterEscapeHandler(null);
                    } else {
                        xmlMarshaller.setCharacterEscapeHandler(new CharacterEscapeHandlerWrapper(value));
                    }
                } else if (XML_DECLARATION.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    Boolean fragment = !(Boolean) value;
                    xmlMarshaller.setFragment(fragment);
                } else if (XML_HEADERS.equals(key)) {
                    xmlMarshaller.setXmlHeader((String) value);
                } else if (OBJECT_IDENTITY_CYCLE_DETECTION.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    xmlMarshaller.setEqualUsingIdenity((Boolean) value);
                } else if (MarshallerProperties.MEDIA_TYPE.equals(key)) {
                    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);
                    }
                    xmlMarshaller.setMediaType(mType);
                } else if (MarshallerProperties.JSON_ATTRIBUTE_PREFIX.equals(key)) {
                    xmlMarshaller.setAttributePrefix((String) value);
                } else if (MarshallerProperties.JSON_INCLUDE_ROOT.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    xmlMarshaller.setIncludeRoot((Boolean) value);
                } else if (MarshallerProperties.JSON_VALUE_WRAPPER.equals(key)) {
                    if (value == null || (((String) value).length() == 0)) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    xmlMarshaller.setValueWrapper((String) value);
                } else if (MarshallerProperties.JSON_NAMESPACE_SEPARATOR.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    xmlMarshaller.setNamespaceSeparator((Character) value);
                } else if (MarshallerProperties.OBJECT_GRAPH.equals(key)) {
                    if (value == null) {
                        xmlMarshaller.setMarshalAttributeGroup(null);
                    } else if (value instanceof ObjectGraphImpl) {
                        xmlMarshaller.setMarshalAttributeGroup(((ObjectGraphImpl) value).getAttributeGroup());
                    } else if (value.getClass() == ClassConstants.STRING) {
                        xmlMarshaller.setMarshalAttributeGroup(value);
                    } else {
                        throw org.eclipse.persistence.exceptions.JAXBException.invalidValueForObjectGraph(value);
                    }
                } else if (MarshallerProperties.BEAN_VALIDATION_MODE.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    this.beanValidationMode = ((BeanValidationMode) value);
                } else if (MarshallerProperties.BEAN_VALIDATION_FACTORY.equals(key)) {
                    //noinspection StatementWithEmptyBody
                    if (value == null) {
                        // Allow null value for preferred validation factory.
                    }
                    this.prefValidatorFactory = value;
                } else if (MarshallerProperties.BEAN_VALIDATION_GROUPS.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    this.beanValidationGroups = ((Class<?>[]) value);
                } else if (MarshallerProperties.BEAN_VALIDATION_NO_OPTIMISATION.equals(key)) {
                    if (value == null) {
                        throw new PropertyException(key, Constants.EMPTY_STRING);
                    }
                    this.bvNoOptimisation = ((boolean) value);
                } else {
                    throw new PropertyException(key, value);
                }
            }
        } catch (ClassCastException exception) {
            throw new PropertyException(key, exception);
        }
    }

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

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

    public JAXBContext getJaxbContext() {
        return jaxbContext;
    }

    public XMLMarshaller getXMLMarshaller() {
        return this.xmlMarshaller;
    }

    /**
     * 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 CharacterEscapeHandlerWrapper extends org.eclipse.persistence.internal.oxm.record.CharacterEscapeHandlerWrapper implements CharacterEscapeHandler {

        public CharacterEscapeHandlerWrapper(Object sunHandler) {
            super(sunHandler);
        }

    }
}
