/*
 * Copyright (c) 2012, 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:
//     Blaise Doughan - 2.4 - initial implementation
package org.eclipse.persistence.jaxb.rs;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NavigableSet;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import jakarta.activation.DataSource;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.StreamingOutput;
import jakarta.ws.rs.ext.ContextResolver;
import jakarta.ws.rs.ext.MessageBodyReader;
import jakarta.ws.rs.ext.MessageBodyWriter;
import jakarta.ws.rs.ext.Provider;
import jakarta.ws.rs.ext.Providers;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.JAXBIntrospector;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.UnmarshalException;
import jakarta.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.exceptions.JSONException;
import org.eclipse.persistence.internal.core.helper.CoreClassConstants;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.localization.JAXBLocalization;
import org.eclipse.persistence.internal.oxm.Constants;
import org.eclipse.persistence.internal.queries.CollectionContainerPolicy;
import org.eclipse.persistence.internal.queries.ContainerPolicy;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.logging.AbstractSessionLog;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.oxm.JSONWithPadding;

/**
 * <p>This is an implementation of <i>MessageBodyReader</i>/<i>MessageBodyWriter
 * </i> that can be used to enable EclipseLink JAXB (MOXy) as the JSON
 * provider.</p>
 * <p>
 * <b>Supported Media Type Patterns</b>
 * <ul>
 * <li>*&#47;json (i.e. application/json and text/json)</li>
 * <li>*&#47;*+json</li>
 * </ul>
 *
 * <p>Below are some different usage options.</p>
 *
 * <b>Option #1 - <i>MOXyJsonProvider</i> Default Behavior</b>
 * <p>You can use the <i>Application</i> class to specify that
 * <i>MOXyJsonProvider</i> should be used with your JAX-RS application.</p>
 * <pre>
 * package org.example;

 * import java.util.*;
 * import jakarta.ws.rs.core.Application;
 * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
 *
 * public class ExampleApplication  extends Application {
 *
 *     &#64;Override
 *     public Set&lt;Class&lt;?&gt;&gt; getClasses() {
 *         HashSet&lt;Class&lt;?&gt;&gt; set = new HashSet&lt;Class&lt;?&gt;&gt;(2);
 *         set.add(MOXyJsonProvider.class);
 *         set.add(ExampleService.class);
 *         return set;
 *     }
 *
 * }
 * </pre>
 *
 * <b>Option #2 - Customize <i>MOXyJsonProvider</i></b>
 * <p>You can use the <i>Application</i> class to specify a configured instance
 * of <i>MOXyJsonProvider</i> should be used with your JAX-RS application.</p>
 * <pre>
 * package org.example;
 *
 * import java.util.*;
 * import jakarta.ws.rs.core.Application;
 * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
 *
 * public class CustomerApplication  extends Application {
 *
 *     &#64;Override
 *     public Set&lt;Class&lt;?&gt;&gt; getClasses() {
 *         HashSet&lt;Class&lt;?&gt;&gt; set = new HashSet&lt;Class&lt;?&gt;&gt;(1);
 *         set.add(ExampleService.class);
 *         return set;
 *     }

 *     &#64;Override
 *     public Set&lt;Object&gt; getSingletons() {
 *         moxyJsonProvider moxyJsonProvider = new MOXyJsonProvider();
 *         moxyJsonProvider.setFormattedOutput(true);
 *         moxyJsonProvider.setIncludeRoot(true);
 *
 *         HashSet&lt;Object&gt; set = new HashSet&lt;Object&gt;(2);
 *         set.add(moxyJsonProvider);
 *         return set;
 *     }
 *
 * }
 * </pre>
 * <b>Option #3 - Extend MOXyJsonProvider</b>
 * <p>You can use MOXyJsonProvider for creating your own
 * <i>MessageBodyReader</i>/<i>MessageBodyWriter</i>.</p>
 * <pre>
 * package org.example;
 *
 * import java.lang.annotation.Annotation;
 * import java.lang.reflect.Type;
 *
 * import jakarta.ws.rs.*;
 * import jakarta.ws.rs.core.*;
 * import jakarta.ws.rs.ext.Provider;
 * import jakarta.xml.bind.*;
 *
 * import org.eclipse.persistence.jaxb.MarshallerProperties;
 * import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider;
 *
 * &#64;Provider
 * &#64;Produces(MediaType.APPLICATION_JSON)
 * &#64;Consumes(MediaType.APPLICATION_JSON)
 * public class CustomerJSONProvider extends MOXyJsonProvider {

 *     &#64;Override
 *     public boolean isReadable(Class&lt;?&gt; type, Type genericType,
 *             Annotation[] annotations, MediaType mediaType) {
 *         return getDomainClass(genericType) == Customer.class;
 *     }
 *
 *     &#64;Override
 *     public boolean isWriteable(Class&lt;?&gt; type, Type genericType,
 *             Annotation[] annotations, MediaType mediaType) {
 *         return isReadable(type, genericType, annotations, mediaType);
 *     }
 *
 *     &#64;Override
 *     protected void preReadFrom(Class&lt;Object&gt; type, Type genericType,
 *             Annotation[] annotations, MediaType mediaType,
 *             MultivaluedMap&lt;String, String&gt; httpHeaders,
 *             Unmarshaller unmarshaller) throws JAXBException {
 *         unmarshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
 *     }
 *
 *     &#64;Override
 *     protected void preWriteTo(Object object, Class&lt;?&gt; type, Type genericType,
 *             Annotation[] annotations, MediaType mediaType,
 *             MultivaluedMap&lt;String, Object&gt; httpHeaders, Marshaller marshaller)
 *             throws JAXBException {
 *         marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, "$");
 *     }
 *
 * }
 * </pre>
 * @since 2.4
 */
@Produces({MediaType.APPLICATION_JSON, MediaType.WILDCARD, "application/x-javascript"})
@Consumes({MediaType.APPLICATION_JSON, MediaType.WILDCARD})
@Provider
public class MOXyJsonProvider implements MessageBodyReader<Object>, MessageBodyWriter<Object>{

    private static final String APPLICATION_XJAVASCRIPT = "application/x-javascript";
    private static final String CHARSET = "charset";
    private static final QName EMPTY_STRING_QNAME = new QName("");
    private static final String JSON = "json";
    private static final String PLUS_JSON = "+json";

    @Context
    protected Providers providers;

    private String attributePrefix = null;
    private Map<Set<Class<?>>, JAXBContext> contextCache = new HashMap<Set<Class<?>>, JAXBContext>();
    private boolean formattedOutput = false;
    private boolean includeRoot = false;
    private boolean marshalEmptyCollections = true;
    private Map<String, String> namespacePrefixMapper;
    private char namespaceSeperator = Constants.DOT;
    private String valueWrapper;
    private boolean wrapperAsArrayName = false;

    /**
     * The value that will be prepended to all keys that are mapped to an XML
     * attribute.  By default there is no attribute prefix.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_ATTRIBUTE_PREFIX
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_ATTRIBUTE_PREFIX
     */
    public String getAttributePrefix() {
        return attributePrefix;
    }

    /**
     * A convenience method to get the domain class (i.e. <i>Customer</i> or <i>Foo, Bar</i>) from
     * the parameter/return type (i.e. <i>Customer</i>, <i>List&lt;Customer&gt;</i>,
     * <i>JAXBElement&lt;Customer&gt;</i>, <i>JAXBElement&lt;? extends Customer&gt;</i>,
     * <i>List&lt;JAXBElement&lt;Customer&gt;&gt;</i>, or
     * <i>List&lt;JAXBElement&lt;? extends Customer&gt;&gt;</i>
     * <i>List&lt;Foo&lt;Bar&gt;&gt;</i>).
     * @param genericType - The parameter/return type of the JAX-RS operation.
     * @return The corresponding domain classes.
     */
    protected Set<Class<?>> getDomainClasses(Type genericType) {
        if(null == genericType) {
            return asSet(Object.class);
        }
        if(genericType instanceof Class && genericType != JAXBElement.class) {
            Class<?> clazz = (Class<?>) genericType;
            if(clazz.isArray()) {
                return getDomainClasses(clazz.getComponentType());
            }
            return asSet(clazz);
        } else if(genericType instanceof ParameterizedType) {
            Set<Class<?>> result = new LinkedHashSet<Class<?>>();
            result.add((Class<?>)((ParameterizedType) genericType).getRawType());
            Type[] types = ((ParameterizedType) genericType).getActualTypeArguments();
            if(types.length > 0){
                for (Type upperType : types) {
                    result.addAll(getDomainClasses(upperType));
                }
            }
            return result;
        } else if (genericType instanceof GenericArrayType) {
            GenericArrayType genericArrayType = (GenericArrayType) genericType;
            return getDomainClasses(genericArrayType.getGenericComponentType());
        } else if(genericType instanceof WildcardType) {
            Set<Class<?>> result = new LinkedHashSet<Class<?>>();
            Type[] upperTypes = ((WildcardType)genericType).getUpperBounds();
            if(upperTypes.length > 0){
                for (Type upperType : upperTypes) {
                    result.addAll(getDomainClasses(upperType));
                }
            } else {
                result.add(Object.class);
            }
            return result;
        } else {
            return asSet(Object.class);
        }
    }

    private Set<Class<?>> asSet(Class<?> clazz) {
        Set<Class<?>> result = new LinkedHashSet<>();
        result.add(clazz);
        return result;
    }

    /**
     * Return the <i>JAXBContext</i> that corresponds to the domain class.  This
     * method does the following:
     * <ol>
     * <li>If an EclipseLink JAXB (MOXy) <i>JAXBContext</i> is available from
     * a <i>ContextResolver</i> then use it.</li>
     * <li>If an existing <i>JAXBContext</i> was not found in step one, then
     * create a new one on the domain class.</li>
     * </ol>
     * @param domainClasses - The domain classes we need a <i>JAXBContext</i> for.
     * @param annotations - The annotations corresponding to domain object.
     * @param mediaType - The media type for the HTTP entity.
     * @param httpHeaders - HTTP headers associated with HTTP entity.
     */
    protected JAXBContext getJAXBContext(Set<Class<?>> domainClasses, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, ?> httpHeaders) throws JAXBException {

        JAXBContext jaxbContext = contextCache.get(domainClasses);
        if(null != jaxbContext) {
            return jaxbContext;
        }

        synchronized (contextCache) {
            jaxbContext = contextCache.get(domainClasses);
            if(null != jaxbContext) {
                return jaxbContext;
            }

            ContextResolver<JAXBContext> resolver = null;
            if(null != providers) {
                resolver = providers.getContextResolver(JAXBContext.class, mediaType);
            }

            if (null != resolver && domainClasses.size() == 1) {
                jaxbContext = resolver.getContext(domainClasses.iterator().next());
            }

            if(null == jaxbContext) {
                jaxbContext = JAXBContextFactory.createContext(domainClasses.toArray(new Class[0]), null);
                contextCache.put(domainClasses, jaxbContext);
                return jaxbContext;
            } else if (jaxbContext instanceof org.eclipse.persistence.jaxb.JAXBContext) {
                return jaxbContext;
            } else {
                jaxbContext = JAXBContextFactory.createContext(domainClasses.toArray(new Class[0]), null);
                contextCache.put(domainClasses, jaxbContext);
                return jaxbContext;
            }
        }
    }

    private JAXBContext getJAXBContext(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        if(null == genericType) {
            genericType = type;
        }

        try {
            Set<Class<?>> domainClasses = getDomainClasses(genericType);
            return getJAXBContext(domainClasses, annotations, mediaType, null);
        } catch(JAXBException e) {
            AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, SessionLog.MOXY, e);
            return null;
        }
    }

    /**
     * By default the JSON-binding will ignore namespace qualification. If this
     * property is set the portion of the key before the namespace separator
     * will be used to determine the namespace URI.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#NAMESPACE_PREFIX_MAPPER
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_PREFIX_MAPPER
     */
    public Map<String, String> getNamespacePrefixMapper() {
        return namespacePrefixMapper;
    }

    /**
     * This character (default is '.') separates the prefix from the key name.
     * It is only used if namespace qualification has been enabled be setting a
     * namespace prefix mapper.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_NAMESPACE_SEPARATOR
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_SEPARATOR
     */
    public char getNamespaceSeparator() {
        return this.namespaceSeperator;
    }

    /*
     * @return -1 since the size of the JSON message is not known.
     * @see jakarta.ws.rs.ext.MessageBodyWriter#getSize(java.lang.Object, java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType)
     */
    @Override
    public long getSize(Object t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        return -1;
    }

    /**
     * The key that will correspond to the property mapped with @XmlValue.  This
     * key will only be used if there are other mapped properties.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_VALUE_WRAPPER
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_VALUE_WRAPPER
     */
    public String getValueWrapper() {
        return valueWrapper;
    }

    /**
     * @return true if the JSON output should be formatted (default is false).
     */
    public boolean isFormattedOutput() {
        return formattedOutput;
    }

    /**
     * @return true if the root node is included in the JSON message (default is
     * false).
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_INCLUDE_ROOT
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_INCLUDE_ROOT
     */
    public boolean isIncludeRoot() {
        return includeRoot;
    }

    /**
     * If true empty collections will be marshalled as empty arrays, else the
     * collection will not be marshalled to JSON (default is true).
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_MARSHAL_EMPTY_COLLECTIONS
     */
    public boolean isMarshalEmptyCollections() {
        return marshalEmptyCollections;
    }

    /**
     * @return true indicating that <i>MOXyJsonProvider</i> will
     * be used for the JSON binding if the media type is of the following
     * patterns *&#47;json or *&#47;*+json, and the type is not assignable from
     * any of (or a Collection or JAXBElement of) the following:
     * <ul>
     * <li>byte[]</li>
     * <li>java.io.File</li>
     * <li>java.io.InputStream</li>
     * <li>java.io.Reader</li>
     * <li>java.lang.Object</li>
     * <li>java.lang.String</li>
     * <li>jakarta.activation.DataSource</li>
     * </ul>
     */
    @Override
    public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        if(!supportsMediaType(mediaType)) {
            return false;
        } else if(CoreClassConstants.APBYTE == type || CoreClassConstants.STRING == type) {
            return false;
        } else if(Map.class.isAssignableFrom(type)) {
            return false;
        } else if(File.class.isAssignableFrom(type)) {
            return false;
        } else if(DataSource.class.isAssignableFrom(type)) {
            return false;
        } else if(InputStream.class.isAssignableFrom(type)) {
            return false;
        } else if(Reader.class.isAssignableFrom(type)) {
            return false;
        } else if(Object.class == type) {
            return false;
        } else if(type.isPrimitive()) {
            return false;
        } else if(type.isArray() && (type.getComponentType().isArray() || type.getComponentType().isPrimitive() || type.getComponentType().getPackage().getName().startsWith("java."))) {
            return false;
        } else if(JAXBElement.class.isAssignableFrom(type)) {
            Set<Class<?>> domainClasses = getDomainClasses(genericType);
            for (Class<?> domainClass : domainClasses) {
                if (isReadable(domainClass, null, annotations, mediaType) || String.class == domainClass) {
                    return true;
                }
            }
            return false;
        } else if(Collection.class.isAssignableFrom(type)) {
            Set<Class<?>> domainClasses = getDomainClasses(genericType);
            for (Class<?> domainClass : domainClasses) {
                if (isReadable(domainClass, null, annotations, mediaType) || String.class == domainClass) {
                    return true;
                }
            }
            return false;
        } else {
            return null != getJAXBContext(type, genericType, annotations, mediaType);
        }
    }

    /**
     * If true the grouping element will be used as the JSON key.
     *
     * <p><b>Example</b></p>
     * <p>Given the following class:</p>
     * <pre>
     * &#64;XmlAccessorType(XmlAccessType.FIELD)
     * public class Customer {
     *
     *     &#64;XmlElementWrapper(name="phone-numbers")
     *     &#64;XmlElement(name="phone-number")
     *     private {@literal List<PhoneNumber>} phoneNumbers;
     *
     * }
     * </pre>
     * <p>If the property is set to false (the default) the JSON output will be:</p>
     * <pre>
     * {
     *     "phone-numbers" : {
     *         "phone-number" : [ {
     *             ...
     *         }, {
     *             ...
     *         }]
     *     }
     * }
     * </pre>
     * <p>And if the property is set to true, then the JSON output will be:</p>
     * <pre>
     * {
     *     "phone-numbers" : [ {
     *         ...
     *     }, {
     *         ...
     *     }]
     * }
     * </pre>
     * @since 2.4.2
     * @see org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_WRAPPER_AS_ARRAY_NAME
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
     */
    public boolean isWrapperAsArrayName() {
        return wrapperAsArrayName;
    }

    /**
     * @return true indicating that <i>MOXyJsonProvider</i> will
     * be used for the JSON binding if the media type is of the following
     * patterns *&#47;json or *&#47;*+json, and the type is not assignable from
     * any of (or a Collection or JAXBElement of) the following:
     * <ul>
     * <li>byte[]</li>
     * <li>java.io.File</li>
     * <li>java.lang.Object</li>
     * <li>java.lang.String</li>
     * <li>jakarta.activation.DataSource</li>
     * <li>jakarta.ws.rs.core.StreamingOutput</li>
     * </ul>
     */
    @Override
    public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
        if(type == JSONWithPadding.class && APPLICATION_XJAVASCRIPT.equals(mediaType.toString())) {
            return true;
        }
        if(!supportsMediaType(mediaType)) {
            return false;
        } else if(CoreClassConstants.APBYTE == type || CoreClassConstants.STRING == type || type.isPrimitive()) {
            return false;
        } else if(Map.class.isAssignableFrom(type)) {
            return false;
        } else if(File.class.isAssignableFrom(type)) {
            return false;
        } else if(DataSource.class.isAssignableFrom(type)) {
            return false;
        } else if(StreamingOutput.class.isAssignableFrom(type)) {
            return false;
        } else if(Object.class == type) {
            return false;
        } else if(type.isPrimitive()) {
            return false;
        } else if(type.isArray() && (String.class.equals(type.getComponentType()) || type.getComponentType().isPrimitive() || Helper.isPrimitiveWrapper(type.getComponentType()))) {
                return true;
        } else if(type.isArray() && (type.getComponentType().isArray() || type.getComponentType().isPrimitive() || type.getComponentType().getPackage().getName().startsWith("java."))) {
            return false;
        } else if(JAXBElement.class.isAssignableFrom(type)) {
            Set<Class<?>> domainClasses = getDomainClasses(genericType);

            for (Class<?> domainClass : domainClasses) {
                if (isWriteable(domainClass, null, annotations, mediaType) || domainClass == String.class) {
                    return true;
                }
            }

            return false;
        } else if(Collection.class.isAssignableFrom(type)) {
            Set<Class<?>> domainClasses = getDomainClasses(genericType);

            //special case for List<JAXBElement<String>>
            //this is quick fix, MOXyJsonProvider should be refactored as stated in issue #459541
            if (domainClasses.size() == 3) {
                Class[] domainArray = domainClasses.toArray(new Class[domainClasses.size()]);
                if (JAXBElement.class.isAssignableFrom(domainArray[1]) && String.class == domainArray[2]) {
                    return true;
                }
            }

            for (Class<?> domainClass : domainClasses) {

                if (String.class.equals(domainClass) || domainClass.isPrimitive() || Helper.isPrimitiveWrapper(domainClass)) {
                    return true;
                }

                    String packageName = domainClass.getPackage().getName();
                if(null == packageName || !packageName.startsWith("java.")) {
                    if (isWriteable(domainClass, null, annotations, mediaType)) {
                        return true;
                    }
                }
            }
            return false;
         } else {
             return null != getJAXBContext(type, genericType, annotations, mediaType);
        }
    }

    /**
     * Subclasses of <i>MOXyJsonProvider</i> can override this method to
     * customize the instance of <i>Unmarshaller</i> that will be used to
     * unmarshal the JSON message in the readFrom call.
     * @param type - The Class to be unmarshalled (i.e. <i>Customer</i> or
     * <i>List</i>)
     * @param genericType - The type of object to be unmarshalled (i.e
     * <i>Customer</i> or <i>List&lt;Customer&gt;</i>).
     * @param annotations - The annotations corresponding to domain object.
     * @param mediaType - The media type for the HTTP entity.
     * @param httpHeaders - HTTP headers associated with HTTP entity.
     * @param unmarshaller - The instance of <i>Unmarshaller</i> that will be
     * used to unmarshal the JSON message.
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties
     */
    protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, Unmarshaller unmarshaller) throws JAXBException {
    }

    /**
     * Subclasses of <i>MOXyJsonProvider</i> can override this method to
     * customize the instance of <i>Marshaller</i> that will be used to marshal
     * the domain objects to JSON in the writeTo call.
     * @param object - The domain object that will be marshalled to JSON.
     * @param type - The Class to be marshalled (i.e. <i>Customer</i> or
     * <i>List</i>)
     * @param genericType - The type of object to be marshalled (i.e
     * <i>Customer</i> or <i>List&lt;Customer&gt;</i>).
     * @param annotations - The annotations corresponding to domain object.
     * @param mediaType - The media type for the HTTP entity.
     * @param httpHeaders - HTTP headers associated with HTTP entity.
     * @param marshaller - The instance of <i>Marshaller</i> that will be used
     * to marshal the domain object to JSON.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties
     */
    protected void preWriteTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, Marshaller marshaller) throws JAXBException {
    }

    /*
     * @see jakarta.ws.rs.ext.MessageBodyReader#readFrom(java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType, jakarta.ws.rs.core.MultivaluedMap, java.io.InputStream)
     */
    @Override
    public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException, WebApplicationException {
        try {
            if(null == genericType) {
                genericType = type;
            }

            Set<Class<?>> domainClasses = getDomainClasses(genericType);
            JAXBContext jaxbContext = getJAXBContext(domainClasses, annotations, mediaType, httpHeaders);
            SessionLog logger = AbstractSessionLog.getLog();

            if (logger.shouldLog(SessionLog.FINE, SessionLog.MOXY)) {
                logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_read_from_moxy_json_provider", new Object[0]);
            }
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
            unmarshaller.setProperty(UnmarshallerProperties.JSON_ATTRIBUTE_PREFIX, attributePrefix);
            unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);
            unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_PREFIX_MAPPER, namespacePrefixMapper);
            unmarshaller.setProperty(UnmarshallerProperties.JSON_NAMESPACE_SEPARATOR, namespaceSeperator);
            if(null != valueWrapper) {
                unmarshaller.setProperty(UnmarshallerProperties.JSON_VALUE_WRAPPER, valueWrapper);
            }
            unmarshaller.setProperty(UnmarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, wrapperAsArrayName);
            preReadFrom(type, genericType, annotations, mediaType, httpHeaders, unmarshaller);

            StreamSource jsonSource;
            Map<String, String> mediaTypeParameters = null;
            if(null != mediaType) {
                mediaTypeParameters = mediaType.getParameters();
            }
            if(null != mediaTypeParameters && mediaTypeParameters.containsKey(CHARSET)) {
                String charSet = mediaTypeParameters.get(CHARSET);
                Reader entityReader = new InputStreamReader(entityStream, charSet);
                jsonSource = new StreamSource(entityReader);
            } else {
                jsonSource = new StreamSource(entityStream);
            }

            Class<?> domainClass = getDomainClass(domainClasses);
            JAXBElement<?> jaxbElement = unmarshaller.unmarshal(jsonSource, domainClass);
            if(type.isAssignableFrom(JAXBElement.class)) {
                return jaxbElement;
            } else {
                Object value = jaxbElement.getValue();
                if(value instanceof ArrayList) {
                    if(type.isArray()) {
                        ArrayList<Object> arrayList = (ArrayList<Object>) value;
                        int arrayListSize = arrayList.size();
                        boolean wrapItemInJAXBElement = wrapItemInJAXBElement(genericType);
                        Object array;
                        if(wrapItemInJAXBElement) {
                            array = Array.newInstance(JAXBElement.class, arrayListSize);
                        } else {
                            array = Array.newInstance(domainClass, arrayListSize);
                        }
                        for(int x=0; x<arrayListSize; x++) {
                            Object element = handleJAXBElement(arrayList.get(x), domainClass, wrapItemInJAXBElement);
                            Array.set(array, x, element);
                        }
                        return array;
                    } else {
                        ContainerPolicy containerPolicy;
                        if(type.isAssignableFrom(List.class) || type.isAssignableFrom(ArrayList.class) || type.isAssignableFrom(Collection.class)) {
                            containerPolicy = new CollectionContainerPolicy(ArrayList.class);
                        } else if(type.isAssignableFrom(Set.class)) {
                            containerPolicy = new CollectionContainerPolicy(HashSet.class);
                        } else if(type.isAssignableFrom(Deque.class) || type.isAssignableFrom(Queue.class)) {
                            containerPolicy = new CollectionContainerPolicy(LinkedList.class);
                        } else if(type.isAssignableFrom(NavigableSet.class) || type.isAssignableFrom(SortedSet.class)) {
                            containerPolicy = new CollectionContainerPolicy(TreeSet.class);
                        } else {
                            containerPolicy = new CollectionContainerPolicy(type);
                        }
                        Object container = containerPolicy.containerInstance();
                        boolean wrapItemInJAXBElement = wrapItemInJAXBElement(genericType);
                        for(Object element : (Collection<Object>) value) {
                            element = handleJAXBElement(element, domainClass, wrapItemInJAXBElement);
                            containerPolicy.addInto(element, container, null);
                        }
                        return container;
                    }
                } else {
                    return value;
                }
            }
        } catch(UnmarshalException unmarshalException) {
            ResponseBuilder builder = Response.status(Status.BAD_REQUEST);
            throw new WebApplicationException(unmarshalException, builder.build());
        } catch(JAXBException jaxbException) {
            throw new WebApplicationException(jaxbException);
        } catch(NullPointerException nullPointerException) {
            throw new WebApplicationException(JSONException.errorInvalidDocument(nullPointerException));
        }
    }

    /**
     * Get first non java class if exists.
     *
     * @return first domain class or first generic class or just the first class from the list
     */
    public Class<?> getDomainClass(Set<Class<?>> domainClasses) {

        if (domainClasses.size() == 1) {
            return domainClasses.iterator().next();
        }

        boolean isStringPresent = false;

        for (Class<?> clazz : domainClasses) {
            if (!clazz.getName().startsWith("java.")
                    && !clazz.getName().startsWith("javax.")
                    && !clazz.getName().startsWith("jakarta.")
                    && !java.util.List.class.isAssignableFrom(clazz)) {
                return clazz;
            } else if (clazz == String.class) {
                isStringPresent = true;
            }
        }

        if (isStringPresent) {
            return String.class;
        }

        //handle simple generic case
        if (domainClasses.size() >= 2) {
            Iterator<Class<?>> it = domainClasses.iterator();
            it.next();
            return it.next();
        }

        return domainClasses.iterator().next();
    }

    private boolean wrapItemInJAXBElement(Type genericType) {
        if(genericType == JAXBElement.class) {
            return true;
        } else if(genericType instanceof GenericArrayType) {
            return wrapItemInJAXBElement(((GenericArrayType) genericType).getGenericComponentType());
        } else if(genericType instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) genericType;
            Type actualType = parameterizedType.getActualTypeArguments()[0];
            return wrapItemInJAXBElement(parameterizedType.getOwnerType()) || wrapItemInJAXBElement(parameterizedType.getRawType()) || wrapItemInJAXBElement(actualType);
        } else {
            return false;
        }
    }

    private Object handleJAXBElement(Object element, Class domainClass, boolean wrapItemInJAXBElement) {
        if(wrapItemInJAXBElement) {
            if(element instanceof JAXBElement) {
                return element;
            } else {
                return new JAXBElement(EMPTY_STRING_QNAME, domainClass, element);
            }
        } else {
            return JAXBIntrospector.getValue(element);
        }
    }

    /**
     * Specify a value that will be prepended to all keys that are mapped to an
     * XML attribute.  By default there is no attribute prefix.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_ATTRIBUTE_PREFIX
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_ATTRIBUTE_PREFIX
     */
    public void setAttributePrefix(String attributePrefix) {
        this.attributePrefix = attributePrefix;
    }

    /**
     * Specify if the JSON output should be formatted (default is false).
     * @param formattedOutput - true if the output should be formatted, else
     * false.
     */
    public void setFormattedOutput(boolean formattedOutput) {
        this.formattedOutput = formattedOutput;
    }

    /**
     * Specify if the root node should be included in the JSON message (default
     * is false).
     * @param includeRoot - true if the message includes the root node, else
     * false.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_INCLUDE_ROOT
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_INCLUDE_ROOT
     */
    public void setIncludeRoot(boolean includeRoot) {
        this.includeRoot = includeRoot;
    }

    /**
     * If true empty collections will be marshalled as empty arrays, else the
     * collection will not be marshalled to JSON (default is true).
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_MARSHAL_EMPTY_COLLECTIONS
     */
    public void setMarshalEmptyCollections(boolean marshalEmptyCollections) {
        this.marshalEmptyCollections = marshalEmptyCollections;
    }

   /**
     * By default the JSON-binding will ignore namespace qualification. If this
     * property is set then a prefix corresponding to the namespace URI and a
     * namespace separator will be prefixed to the key.
     * include it you can specify a Map of namespace URI to prefix.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#NAMESPACE_PREFIX_MAPPER
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_PREFIX_MAPPER
     */
    public void setNamespacePrefixMapper(Map<String, String> namespacePrefixMapper) {
        this.namespacePrefixMapper = namespacePrefixMapper;
    }

    /**
     * This character (default is '.') separates the prefix from the key name.
     * It is only used if namespace qualification has been enabled be setting a
     * namespace prefix mapper.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_NAMESPACE_SEPARATOR
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_NAMESPACE_SEPARATOR
     */
    public void setNamespaceSeparator(char namespaceSeparator) {
        this.namespaceSeperator = namespaceSeparator;
    }

    /**
     * If true the grouping element will be used as the JSON key.
     *
     * <p><b>Example</b></p>
     * <p>Given the following class:</p>
     * <pre>
     * &#64;XmlAccessorType(XmlAccessType.FIELD)
     * public class Customer {
     *
     *     &#64;XmlElementWrapper(name="phone-numbers")
     *     &#64;XmlElement(name="phone-number")
     *     private {@literal List<PhoneNumber>} phoneNumbers;
     *
     * }
     * </pre>
     * <p>If the property is set to false (the default) the JSON output will be:</p>
     * <pre>
     * {
     *     "phone-numbers" : {
     *         "phone-number" : [ {
     *             ...
     *         }, {
     *             ...
     *         }]
     *     }
     * }
     * </pre>
     * <p>And if the property is set to true, then the JSON output will be:</p>
     * <pre>
     * {
     *     "phone-numbers" : [ {
     *         ...
     *     }, {
     *         ...
     *     }]
     * }
     * </pre>
     * @since 2.4.2
     * @see org.eclipse.persistence.jaxb.JAXBContextProperties#JSON_WRAPPER_AS_ARRAY_NAME
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_WRAPPER_AS_ARRAY_NAME
     */
    public void setWrapperAsArrayName(boolean wrapperAsArrayName) {
        this.wrapperAsArrayName = wrapperAsArrayName;
    }

    /**
     * Specify the key that will correspond to the property mapped with
     * {@literal @XmlValue}.  This key will only be used if there are other mapped
     * properties.
     * @see org.eclipse.persistence.jaxb.MarshallerProperties#JSON_VALUE_WRAPPER
     * @see org.eclipse.persistence.jaxb.UnmarshallerProperties#JSON_VALUE_WRAPPER
     */
    public void setValueWrapper(String valueWrapper) {
        this.valueWrapper = valueWrapper;
    }

    /**
     * @return true for all media types of the pattern *&#47;json and
     * *&#47;*+json.
     */
    protected boolean supportsMediaType(MediaType mediaType) {
        if(null == mediaType) {
            return true;
        }
        String subtype = mediaType.getSubtype();
        return subtype.equals(JSON) || subtype.endsWith(PLUS_JSON);
    }

    /**
     * @see jakarta.ws.rs.ext.MessageBodyWriter#writeTo(java.lang.Object, java.lang.Class, java.lang.reflect.Type, java.lang.annotation.Annotation[], jakarta.ws.rs.core.MediaType, jakarta.ws.rs.core.MultivaluedMap, java.io.OutputStream)
     */
    @Override
    public void writeTo(Object object, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException {
        try {
            if(null == genericType) {
                genericType = type;
            }

            Set<Class<?>> domainClasses = getDomainClasses(genericType);
            JAXBContext jaxbContext = getJAXBContext(domainClasses, annotations, mediaType, httpHeaders);
            SessionLog logger = AbstractSessionLog.getLog();

            if (logger.shouldLog(SessionLog.FINE, SessionLog.MOXY)) {
                logger.log(SessionLog.FINE, SessionLog.MOXY, "moxy_write_to_moxy_json_provider", new Object[0]);
            }
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, formattedOutput);
            marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, MediaType.APPLICATION_JSON);
            marshaller.setProperty(MarshallerProperties.JSON_ATTRIBUTE_PREFIX, attributePrefix);
            marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, includeRoot);
            marshaller.setProperty(MarshallerProperties.JSON_MARSHAL_EMPTY_COLLECTIONS, marshalEmptyCollections);
            marshaller.setProperty(MarshallerProperties.JSON_NAMESPACE_SEPARATOR, namespaceSeperator);
            if(null != valueWrapper) {
                marshaller.setProperty(MarshallerProperties.JSON_VALUE_WRAPPER, valueWrapper);
            }
            marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, wrapperAsArrayName);
            marshaller.setProperty(MarshallerProperties.NAMESPACE_PREFIX_MAPPER, namespacePrefixMapper);

            Map<String, String> mediaTypeParameters = null;
            if(null != mediaType) {
                mediaTypeParameters = mediaType.getParameters();
            }
            if(null != mediaTypeParameters && mediaTypeParameters.containsKey(CHARSET)) {
                String charSet = mediaTypeParameters.get(CHARSET);
                marshaller.setProperty(Marshaller.JAXB_ENCODING, charSet);
            }

            preWriteTo(object, type, genericType, annotations, mediaType, httpHeaders, marshaller);
            if (domainClasses.size() == 1) {
                Class<?> domainClass = domainClasses.iterator().next();
                if(!(List.class.isAssignableFrom(type) ||  type.isArray()) && domainClass.getPackage().getName().startsWith("java.")) {
                    object = new JAXBElement(new QName((String) marshaller.getProperty(MarshallerProperties.JSON_VALUE_WRAPPER)), domainClass, object);
                }
            }

            marshaller.marshal(object, entityStream);
        } catch(JAXBException jaxbException) {
            throw new WebApplicationException(jaxbException);
        }
    }
}
