/*
 * Copyright (c) 2011, 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:
//        dclarke/tware - initial
//     2014-09-01-2.6.0 Dmitry Kornilov
//       - JPARS 2.0 related changes
package org.eclipse.persistence.jpa.rs;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
import jakarta.persistence.Query;
import jakarta.persistence.RollbackException;
import jakarta.persistence.spi.PersistenceUnitInfo;
import jakarta.ws.rs.core.MediaType;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.Unmarshaller;
import jakarta.xml.bind.ValidationEvent;
import jakarta.xml.bind.ValidationEventHandler;
import jakarta.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.stream.StreamSource;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.FetchGroupManager;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.dynamic.DynamicType;
import org.eclipse.persistence.eis.mappings.EISCompositeCollectionMapping;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.internal.jaxb.SessionEventListener;
import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryImpl;
import org.eclipse.persistence.internal.jpa.rs.weaving.PersistenceWeavedRest;
import org.eclipse.persistence.internal.jpa.rs.weaving.RelationshipInfo;
import org.eclipse.persistence.internal.jpa.rs.weaving.RestAdapterClassWriter;
import org.eclipse.persistence.internal.jpa.rs.weaving.RestCollectionAdapterClassWriter;
import org.eclipse.persistence.internal.jpa.rs.weaving.RestReferenceAdapterV2ClassWriter;
import org.eclipse.persistence.internal.security.PrivilegedAccessHelper;
import org.eclipse.persistence.internal.security.PrivilegedGetDeclaredFields;
import org.eclipse.persistence.internal.security.PrivilegedMethodInvoker;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jaxb.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
import org.eclipse.persistence.jaxb.MarshallerProperties;
import org.eclipse.persistence.jaxb.ObjectGraph;
import org.eclipse.persistence.jaxb.UnmarshallerProperties;
import org.eclipse.persistence.jaxb.dynamic.DynamicJAXBContextFactory;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.jpa.PersistenceProvider;
import org.eclipse.persistence.jpa.dynamic.JPADynamicHelper;
import org.eclipse.persistence.jpa.rs.annotations.RestPageableQueries;
import org.eclipse.persistence.jpa.rs.annotations.RestPageableQuery;
import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
import org.eclipse.persistence.jpa.rs.features.FeatureSet;
import org.eclipse.persistence.jpa.rs.features.ServiceVersion;
import org.eclipse.persistence.jpa.rs.features.fieldsfiltering.FieldsFilter;
import org.eclipse.persistence.jpa.rs.util.CollectionWrapperBuilder;
import org.eclipse.persistence.jpa.rs.util.IdHelper;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
import org.eclipse.persistence.jpa.rs.util.JTATransactionWrapper;
import org.eclipse.persistence.jpa.rs.util.ObjectGraphBuilder;
import org.eclipse.persistence.jpa.rs.util.ResourceLocalTransactionWrapper;
import org.eclipse.persistence.jpa.rs.util.TransactionWrapper;
import org.eclipse.persistence.jpa.rs.util.list.ReadAllQueryResultCollection;
import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultCollection;
import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultList;
import org.eclipse.persistence.jpa.rs.util.list.ReportQueryResultListItem;
import org.eclipse.persistence.jpa.rs.util.list.SingleResultQueryList;
import org.eclipse.persistence.jpa.rs.util.xmladapters.LinkAdapter;
import org.eclipse.persistence.jpa.rs.util.xmladapters.RelationshipLinkAdapter;
import org.eclipse.persistence.logging.SessionLog;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ObjectReferenceMapping;
import org.eclipse.persistence.oxm.mappings.XMLInverseReferenceMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.FetchGroup;
import org.eclipse.persistence.queries.FetchGroupTracker;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.UnitOfWork;

/**
 * A wrapper around the JPA and JAXB artifacts used to persist an application.
 *
 * A PersistenceContext provides the capability of using the same persistence unit in JPA to
 * to interact with a Database or other JPA-capable data source and in JAXB to interact with either
 * XML or JSON.
 *
 * A PersistenceContext can wrap either an existing persistence unit (EntityManagerFactory), or it can be used to bootstrap a
 * fully dynamic persistence unit.
 *
 * @author douglas.clarke, tom.ware
 */
public class PersistenceContext {
    public static final String JPARS_CONTEXT = "eclipselink.jpars.context";
    public static final String CLASS_NAME = PersistenceContext.class.getName();
    public static final String SESSION_VERSION_PROPERTY = "jaxb.context.version";

    protected List<XmlAdapter<?, ?>> adapters = null;

    /**
     * The name of the persistence context is used to look it up. By default it will be the
     * persistence unit name of the JPA persistence unit.
     */
    protected String name = null;

    /** The EntityManagerFactory used to interact using JPA **/
    protected EntityManagerFactory emf;

    /** The JAXBConext used to produce JSON or XML **/
    protected JAXBContext jaxbContext = null;

    /** The URI of the Persistence context. This is used to build Links in JSON and XML **/
    protected URI baseURI = null;

    private SessionLog sessionLog = null;

    private TransactionWrapper transaction = null;

    private Boolean weavingEnabled = null;

    private ServiceVersion version = ServiceVersion.VERSION_2_0;

    /** Builder for collection proxies used in JPARS 2.0. **/
    private CollectionWrapperBuilder collectionWrapperBuilder;

    /**
     * JPARS pageable queries map.
     * Key: named query name
     * Value: corresponding RestPageableQuery annotation
     */
    private Map<String, RestPageableQuery> pageableQueries;

    protected PersistenceContext() {
    }

    /**
     * Instantiates a new persistence context.
     *
     * @param emfName the emf name
     * @param emf the emf
     * @param defaultURI the default uri
     */
    public PersistenceContext(String emfName, EntityManagerFactory emf, URI defaultURI) {
        super();
        init(emfName, emf, defaultURI, ServiceVersion.VERSION_2_0);
    }

    /**
     * Instantiates a new persistence context.
     *
     * @param emfName the emf name
     * @param emf the emf
     * @param defaultURI the default uri
     * @param version REST service version
     */
    public PersistenceContext(String emfName, EntityManagerFactory emf, URI defaultURI, ServiceVersion version) {
        super();
        init(emfName, emf, defaultURI, version);
    }

    private void init(String emfName, EntityManagerFactory emf, URI defaultURI, ServiceVersion version) {
        this.emf = emf;
        this.name = emfName;
        this.baseURI = defaultURI;
        this.sessionLog = JpaHelper.getDatabaseSession(emf).getSessionLog();

        if (version != null) {
            this.version = version;
        } else {
            this.version = ServiceVersion.VERSION_2_0;
        }

        if (getServerSession().hasExternalTransactionController()) {
            transaction = new JTATransactionWrapper();
        } else {
            transaction = new ResourceLocalTransactionWrapper();
        }

        try {
            this.jaxbContext = createDynamicJAXBContext(JpaHelper.getServerSession(emf));
        } catch (JAXBException | IOException jaxbe) {
            JPARSLogger.exception(getSessionLog(), "exception_creating_jaxb_context", new Object[] { emfName, jaxbe.toString() }, jaxbe);
            emf.close();
        }
    }

    /**
     * Checks if is weaving enabled.
     *
     * @return true, if is weaving enabled
     */
    public boolean isWeavingEnabled() {
        if (this.weavingEnabled == null) {
            this.weavingEnabled = getWeavingProperty();
        }
        return this.weavingEnabled;
    }

    /**
     * Gets the version as it appears in URI.
     *
     * @return The version.
     */
    public String getVersion() {
        return version.getCode();
    }

    /**
     * Gets JPARS version.
     *
     * @return JPARS version.
     */
    public ServiceVersion getServiceVersion() {
        return version;
    }

    /**
     * This method is used to help construct a JAXBContext from an existing EntityManagerFactory.
     *
     * For each package in the EntityManagerFactory, a MetadataSource that is capable of building a JAXBContext
     * that creates the same mappings in JAXB is created.  These MetadataSources are used to constuct the JAXContext
     * that is used for JSON and XML translation.
     */
    protected void addDynamicXMLMetadataSources(List<Object> metadataSources, Session session) {
        Set<String> packages = new HashSet<>();
        for (Class<?> descriptorClass : session.getDescriptors().keySet()) {
            String packageName = "";
            int lastDotIndex = descriptorClass.getName().lastIndexOf('.');
            if (lastDotIndex > 0) {
                packageName = descriptorClass.getName().substring(0, lastDotIndex);
            }
            if (!packages.contains(packageName)) {
                packages.add(packageName);
            }
        }

        for (String packageName : packages) {
            metadataSources.add(getSupportedFeatureSet().getDynamicMetadataSource(session, packageName));
        }
    }

    /**
     * A part of the facade over the JPA API.
     * Persist an entity in JPA and commit.
     */
    public void create(Map<String, String> tenantId, Object entity) throws Exception {
        EntityManager em = getEmf().createEntityManager(tenantId);
        try {
            transaction.beginTransaction(em);
            em.persist(entity);
            transaction.commitTransaction(em);
        } catch (RollbackException ex) {
            throw ex;
        } catch (Exception ex) {
            transaction.rollbackTransaction(em);
            throw ex;
        } finally {
            em.close();
        }
    }

    /**
     * Create a JAXBContext based on the EntityManagerFactory for this PersistenceContext.
     */
    protected JAXBContext createDynamicJAXBContext(Session session) throws JAXBException, IOException {
        final ServiceVersion cachedContextVersion = (ServiceVersion) session.getProperty(SESSION_VERSION_PROPERTY);
        final JAXBContext cachedContext = (JAXBContext) session.getProperty(JAXBContext.class.getName());
        if (cachedContext != null && cachedContextVersion != null && cachedContextVersion == version) {
            return cachedContext;
        }

        final Map<String, Object> properties = createJAXBProperties(session);
        final ClassLoader cl = session.getDatasourcePlatform().getConversionManager().getLoader();
        final JAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromOXM(cl, properties);

        session.setProperty(SESSION_VERSION_PROPERTY, version);
        session.setProperty(JAXBContext.class.getName(), jaxbContext);

        return jaxbContext;
    }

    /**
     * A part of the facade over the JPA API.
     * Create an EntityManagerFactory using the given PersistenceUnitInfo and properties.
     */
    protected EntityManagerFactory createEntityManagerFactory(PersistenceUnitInfo info, Map<String, ?> properties) {
        PersistenceProvider provider = new PersistenceProvider();
        EntityManagerFactory emf = provider.createContainerEntityManagerFactory(info, properties);
        return emf;
    }

    /**
     * A part of the facade over the JPA API
     * Create an EntityManager from the EntityManagerFactory wrapped by this persistence context
     */
    protected EntityManager createEntityManager(String tenantId) {
        return getEmf().createEntityManager();
    }

    /**
     * Build the set of properties used to create the JAXBContext based on the EntityManagerFactory that
     * this PersistenceContext wraps
     */
    protected Map<String, Object> createJAXBProperties(Session session) throws IOException {
        Map<String, Object> properties = new HashMap<>(1);
        List<Object> metadataLocations = new ArrayList<>();

        addDynamicXMLMetadataSources(metadataLocations, session);

        String oxmLocation = (String) emf.getProperties().get("eclipselink.jpa-rs.oxm");
        if (oxmLocation != null) {
            metadataLocations.add(oxmLocation);
        }

        Object passedOXMLocations = emf.getProperties().get(JAXBContextProperties.OXM_METADATA_SOURCE);
        if (passedOXMLocations != null) {
            if (passedOXMLocations instanceof Collection) {
                metadataLocations.addAll((Collection<?>) passedOXMLocations);
            } else {
                metadataLocations.add(passedOXMLocations);
            }
        }

        // Add static metadata sources specific to current version
        metadataLocations.addAll(getSupportedFeatureSet().getMetadataSources());

        properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, metadataLocations);

        SessionEventListener sessionEventListener = getSupportedFeatureSet().getSessionEventListener(session);
        if (sessionEventListener != null) {
            properties.put(JAXBContextProperties.SESSION_EVENT_LISTENER, sessionEventListener);
        }

        // Bug 410095 - JSON_WRAPPER_AS_ARRAY_NAME property doesn't work when jaxb context is created using DynamicJAXBContextFactory
        //properties.put(JAXBContextProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);

        return properties;
    }

    /**
     *  A part of the facade over the JPA API
     *  Delete the given entity in JPA and commit the changes
     */
    public void delete(Map<String, String> tenantId, String type, Object id) {
        EntityManager em = getEmf().createEntityManager(tenantId);

        try {
            transaction.beginTransaction(em);
            Object entity = em.find(getClass(type), id);
            if (entity != null) {
                em.remove(entity);
            }
            transaction.commitTransaction(em);
        } catch (RollbackException ex) {
            throw JPARSException.exceptionOccurred(ex);
        } catch (Exception ex) {
            transaction.rollbackTransaction(em);
            throw JPARSException.exceptionOccurred(ex);
        } finally {
            em.close();
        }
    }

    /**
     * Does exist.
     *
     * @param tenantId the tenant id
     * @param entity the entity
     * @return true, if successful
     */
    public boolean doesExist(Map<String, String> tenantId, Object entity) {
        DatabaseSession session = JpaHelper.getDatabaseSession(getEmf());
        return session.doesObjectExist(entity);
    }

    /**
     * Finalize.
     */
    @Override
    protected void finalize() throws Throwable {
        emf.close();
        super.finalize();
    }

    /**
     * A part of the facade over the JPA API
     * Find an entity with the given name and id in JPA
     */
    public Object find(String entityName, Object id) {
        return find(null, entityName, id);
    }

    /**
     * A part of the facade over the JPA API
     * Find an entity with the given name and id in JPA
     */
    public Object find(Map<String, String> tenantId, String entityName, Object id) {
        return find(tenantId, entityName, id, null);
    }

    /**
     * A part of the facade over the JPA API
     * Find an entity with the given name and id in JPA
     * @param properties - query hints used on the find
     */
    public Object find(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties) {
        EntityManager em = getEmf().createEntityManager(tenantId);

        try {
            return em.find(getClass(entityName), id, properties);
        } finally {
            em.close();
        }
    }

    /**
     * Update or add attribute.
     *
     * @param tenantId the tenant id
     * @param entityName the entity name
     * @param id the id
     * @param properties the properties
     * @param attribute the attribute
     * @param attributeValue the attribute value
     * @param partner the partner
     * @return the object
     */
    public Object updateOrAddAttribute(Map<String, String> tenantId, String entityName, Object id, Map<String, Object> properties, String attribute, Object attributeValue, String partner) {
        EntityManager em = getEmf().createEntityManager(tenantId);

        try {
            ClassDescriptor descriptor = getServerSession().getClassDescriptor(getClass(entityName));
            DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
            Object object;
            if (mapping == null) {
                return null;
            } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
                DatabaseMapping partnerMapping = null;
                if (partner != null) {
                    ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
                    partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
                    if (partnerMapping == null) {
                        return null;
                    }
                }
                transaction.beginTransaction(em);
                try {
                    object = em.find(getClass(entityName), id, properties);
                    if (object == null) {
                        return null;
                    }
                    attributeValue = em.merge(attributeValue);
                    setMappingValueInObject(object, attributeValue, mapping, partnerMapping);
                    transaction.commitTransaction(em);
                } catch (RollbackException e) {
                    JPARSLogger.exception(getSessionLog(), "exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
                    return null;
                } catch (Exception e) {
                    JPARSLogger.exception(getSessionLog(), "exception_while_updating_attribute", new Object[] { entityName, getName() }, e);
                    transaction.rollbackTransaction(em);
                    return null;
                }
            } else {
                return null;
            }
            return object;
        } finally {
            em.close();
        }
    }

    /**
     * Removes the attribute.
     *
     * @param tenantId the tenant id
     * @param entityName the entity name
     * @param id the id
     * @param attribute the attribute
     * @param partner the partner
     * @return the object
     *
     */
    @SuppressWarnings({"rawtypes" })
    public Object removeAttribute(Map<String, String> tenantId, String entityName, Object id, String attribute, String listItemId, Object entity, String partner)
    {
        EntityManager em = getEmf().createEntityManager(tenantId);
        String fieldName = null;

        try {
            Class<?> clazz = getClass(entityName);
            ClassDescriptor descriptor = getServerSession().getClassDescriptor(clazz);
            DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
            if (mapping == null) {
                return null;
            } else if (mapping.isObjectReferenceMapping() || mapping.isCollectionMapping()) {
                DatabaseMapping partnerMapping = null;
                Object originalAttributeValue = null;
                ClassDescriptor referenceDescriptor = mapping.getReferenceDescriptor();
                if (partner != null) {
                    partnerMapping = referenceDescriptor.getMappingForAttributeName(partner);
                    if (partnerMapping == null) {
                        return null;
                    }
                }
                Field[] fields;
                if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                    fields = AccessController.doPrivileged(new PrivilegedGetDeclaredFields(clazz));
                } else {
                    fields = PrivilegedAccessHelper.getDeclaredFields(clazz);
                }

                for (Field field : fields) {
                    fieldName = field.getName();
                    if (fieldName.equals(attribute)) {
                        try {
                            // call clear on this collection
                            Object attributeValue = getAttribute(entity, attribute);
                            originalAttributeValue = attributeValue;
                            if (attributeValue instanceof Collection) {
                                if (listItemId == null) {
                                    // no collection member specified in request (listItemId=null) remove entire collection
                                    ((Collection) attributeValue).clear();
                                } else {
                                    Object realListItemId = IdHelper.buildId(this, referenceDescriptor.getAlias(), listItemId);
                                    Object member = this.find(referenceDescriptor.getAlias(), realListItemId);
                                    ((Collection) attributeValue).remove(member);
                                }
                            }
                            break;
                        } catch (Exception e) {
                            e.printStackTrace();
                            return null;
                        }
                    }
                }

                transaction.beginTransaction(em);
                entity = em.merge(entity);
                removeMappingValueFromObject(entity, originalAttributeValue, mapping, partnerMapping);
                transaction.commitTransaction(em);
                return entity;
            }
            return null;
        } catch (Exception e) {
            JPARSLogger.exception(getSessionLog(), "exception_while_removing_attribute", new Object[] { fieldName, entityName, getName() }, e);
            transaction.rollbackTransaction(em);
            return null;
        } finally {
            em.close();
        }
    }

    private Object getAttribute(Object entity, String propertyName) {
        try {
            BeanInfo info = Introspector.getBeanInfo(entity.getClass(), Object.class);
            PropertyDescriptor[] props = info.getPropertyDescriptors();
            for (PropertyDescriptor pd : props) {
                String name = pd.getName();
                if (propertyName.equals(name)) {
                    Method getter = pd.getReadMethod();
                    Object value;
                    if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
                        value = AccessController.doPrivileged(new PrivilegedMethodInvoker<>(getter, entity));
                    } else {
                        value = PrivilegedAccessHelper.invokeMethod(getter, entity);
                    }
                    return value;
                }
            }
        } catch (IntrospectionException | PrivilegedActionException | IllegalAccessException | InvocationTargetException ex) {
            return null;
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    protected void removeMappingValueFromObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
        if (mapping.isObjectReferenceMapping()) {
            Object currentValue = mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession());
            if (currentValue.equals(attributeValue)) {
                ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, null, true);
                if (partner != null) {
                    removeMappingValueFromObject(attributeValue, object, partner, null);
                }
            }
        } else if (mapping.isCollectionMapping()) {
            boolean removed = ((Collection) mapping.getRealAttributeValueFromObject(object, (AbstractSession) getServerSession())).remove(attributeValue);
            if (removed && partner != null) {
                removeMappingValueFromObject(attributeValue, object, partner, null);
            }
        }
    }

    /**
     * Gets the base uri.
     *
     * @return the base uri
     */
    public URI getBaseURI() {
        return baseURI;
    }

    /**
     * Look-up the given entity name in the EntityManagerFactory and return the class
     * is describes
     */
    public Class<?> getClass(String entityName) {
        ClassDescriptor descriptor = getDescriptor(entityName);
        if (descriptor == null) {
            return null;
        }
        return descriptor.getJavaClass();
    }

    /**
     * Gets the jpa server session.
     *
     * @return the jpa server session
     */
    public DatabaseSession getServerSession() {
        // Fix for bug 390786 - JPA-RS: ClassCastException retrieving metadata for Composite Persistence Unit
        return JpaHelper.getDatabaseSession(emf);
    }

    /**
     * Gets the client session.
     *
     * @param em the em
     * @return the client session
     */
    public AbstractSession getClientSession(EntityManager em) {
        UnitOfWork uow = JpaHelper.getEntityManager(em).getUnitOfWork();
        return (AbstractSession) uow;
    }

    /**
     * Lookup the descriptor for the given entity name.
     * This method will look first in the EntityManagerFactory wrapped by this persistence context
     * and return that descriptor.  If one does not exist, it search the JAXBContext and return
     * a descriptor from there.
     */
    public ClassDescriptor getDescriptor(String entityName) {
        DatabaseSession session = getServerSession();
        ClassDescriptor descriptor = session.getDescriptorForAlias(entityName);
        if (descriptor == null) {
            for (Object ajaxBSession : getJAXBContext().getXMLContext().getSessions()) {
                descriptor = ((Session) ajaxBSession).getClassDescriptorForAlias(entityName);
                if (descriptor != null) {
                    break;
                }
            }
        }
        return descriptor;
    }

    /**
     * Gets the descriptor for class.
     *
     * @param clazz the clazz
     * @return the descriptor for class
     */
    @SuppressWarnings("rawtypes")
    public ClassDescriptor getDescriptorForClass(Class clazz) {
        DatabaseSession session = getServerSession();
        ClassDescriptor descriptor = session.getDescriptor(clazz);
        if (descriptor == null) {
            return getJAXBDescriptorForClass(clazz);
        }
        return descriptor;
    }

    /**
     * Gets the jAXB descriptor for class.
     *
     * @param clazz the clazz
     * @return the jAXB descriptor for class
     */
    @SuppressWarnings("rawtypes")
    public ClassDescriptor getJAXBDescriptorForClass(Class clazz) {
        ClassDescriptor descriptor = null;
        for (Object ajaxBSession : getJAXBContext().getXMLContext().getSessions()) {
            descriptor = ((Session) ajaxBSession).getClassDescriptor(clazz);
            if (descriptor != null) {
                break;
            }
        }
        return descriptor;
    }

    /**
     * Gets the emf.
     *
     * @return the emf
     */
    public EntityManagerFactory getEmf() {
        return emf;
    }

    /**
     * Gets the jAXB context.
     *
     * @return the jAXB context
     */
    public JAXBContext getJAXBContext() {
        return jaxbContext;
    }

    /**
     * Gets the name.
     *
     * @return the name
     */
    public String getName() {
        return name;
    }

    public SessionLog getSessionLog() {
        return sessionLog;
    }

    /**
     * A part of the facade over the JPA API
     * Call jpa merge on the given object and commit
     * If the passed object is a list, we will iterate through the
     * list and merge each member
     */
    @SuppressWarnings("rawtypes")
    public Object merge(Map<String, String> tenantId, Object entity) {
        EntityManager em = getEmf().createEntityManager(tenantId);
        Object mergedEntity;
        try {
            transaction.beginTransaction(em);
            if (entity instanceof List) {
                List<Object> mergeList = new ArrayList<>();
                for (Object o : (List) entity) {
                    mergeList.add(em.merge(o));
                }
                mergedEntity = mergeList;
            } else {
                mergedEntity = em.merge(entity);
            }
            transaction.commitTransaction(em);
            return mergedEntity;
        } catch (RollbackException ex) {
            throw JPARSException.exceptionOccurred(ex);
        } catch (Exception ex) {
            transaction.rollbackTransaction(em);
            throw JPARSException.exceptionOccurred(ex);
        } finally {
            em.close();
        }
    }

    /**
     * A convenience method to create a new dynamic entity of the given type
     */
    public DynamicEntity newEntity(String type) {
        return newEntity(null, type);
    }

    /**
     * A convenience method to create a new dynamic entity of the given type
     */
    public DynamicEntity newEntity(Map<String, String> tenantId, String type) {
        JPADynamicHelper helper = new JPADynamicHelper(getEmf());
        DynamicEntity entity;
        try {
            entity = helper.newDynamicEntity(type);
        } catch (IllegalArgumentException e) {
            ClassDescriptor descriptor = getDescriptor(type);
            if (descriptor != null) {
                DynamicType jaxbType = (DynamicType) descriptor.getProperty(DynamicType.DESCRIPTOR_PROPERTY);
                if (jaxbType != null) {
                    return jaxbType.newDynamicEntity();
                }
            }
            JPARSLogger.exception(getSessionLog(), "exception_thrown_while_creating_dynamic_entity", new Object[] { type }, e);
            throw e;
        }
        return entity;
    }

    /**
     * Query execute update.
     *
     * @param tenantId the tenant id
     * @param name the name
     * @param parameters the parameters
     * @param hints the hints
     * @return the int
     */
    public int queryExecuteUpdate(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
        EntityManager em = getEmf().createEntityManager(tenantId);
        try {
            Query query = constructQuery(em, name, parameters, hints);
            transaction.beginTransaction(em);
            int result = query.executeUpdate();
            transaction.commitTransaction(em);
            return result;
        } catch (RollbackException ex) {
            throw JPARSException.exceptionOccurred(ex);
        } catch (Exception ex) {
            transaction.rollbackTransaction(em);
            throw JPARSException.exceptionOccurred(ex);
        } finally {
            em.close();
        }
    }

    /**
     * Query multiple results.
     *
     * @param tenantId the tenant id
     * @param name the name
     * @param parameters the parameters
     * @param hints the hints
     * @return the list
     */
    @SuppressWarnings("rawtypes")
    public List queryMultipleResults(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
        EntityManager em = getEmf().createEntityManager(tenantId);
        try {
            Query query = constructQuery(em, name, parameters, hints);
            return query.getResultList();
        } finally {
            em.close();
        }
    }

    protected Query constructQuery(EntityManager em, String name, Map<?, ?> parameters, Map<String, ?> hints) {
        Query query = em.createNamedQuery(name);
        DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
        if (parameters != null) {
            Iterator<?> i = parameters.entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
                String key = (String) entry.getKey();
                Class<?> parameterClass = null;
                int index = dbQuery.getArguments().indexOf(key);
                if (index >= 0) {
                    parameterClass = dbQuery.getArgumentTypes().get(index);
                }
                Object parameter = entry.getValue();
                if (parameterClass != null) {
                    parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
                }
                query.setParameter(key, parameter);
            }
        }
        if (hints != null) {
            for (Map.Entry<String, ?> entry : hints.entrySet()) {
                query.setHint(entry.getKey(), entry.getValue());
            }
        }
        return query;
    }

    /**
     * Builds the query.
     *
     * @param tenantId the tenant id
     * @param name the name
     * @param parameters the parameters
     * @param hints the hints
     * @return the query
     */
    public Query buildQuery(Map<String, String> tenantId, String name, Map<?, ?> parameters, Map<String, ?> hints) {
        EntityManager em = getEmf().createEntityManager(tenantId);
        Query query = em.createNamedQuery(name);
        DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
        if (parameters != null) {
            Iterator<?> i = parameters.entrySet().iterator();
            while (i.hasNext()) {
                Map.Entry<?, ?> entry = (Map.Entry<?, ?>) i.next();
                String key = (String) entry.getKey();
                Class<?> parameterClass = null;
                int index = dbQuery.getArguments().indexOf(key);
                if (index >= 0) {
                    parameterClass = dbQuery.getArgumentTypes().get(index);
                }
                Object parameter = entry.getValue();
                if (parameterClass != null) {
                    parameter = ConversionManager.getDefaultManager().convertObject(parameter, parameterClass);
                }
                query.setParameter(key, parameter);
            }
        }
        if (hints != null) {
            for (Map.Entry<String, ?> entry : hints.entrySet()) {
                query.setHint(entry.getKey(), entry.getValue());
            }
        }
        return query;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected void setMappingValueInObject(Object object, Object attributeValue, DatabaseMapping mapping, DatabaseMapping partner) {
        if (mapping.isObjectReferenceMapping()) {
            ((ObjectReferenceMapping) mapping).getIndirectionPolicy().setRealAttributeValueInObject(object, attributeValue, true);
            if (partner != null) {
                setMappingValueInObject(attributeValue, object, partner, null);
            }
        } else if (mapping.isCollectionMapping()) {
            ((Collection) mapping.getAttributeValueFromObject(object)).add(attributeValue);
            if (partner != null) {
                setMappingValueInObject(attributeValue, object, partner, null);
            }
        }
    }

    /**
     * Stop the current application instance
     */
    public void stop() {
        if (emf != null && emf.isOpen()) {
            emf.close();
        }
        this.emf = null;
        this.jaxbContext = null;
    }

    /**
     * To string.
     *
     * @return the string
     */
    @Override
    public String toString() {
        return "PersistenceContext(name:" + getName() + ", version:" + getVersion() + ", identityHashCode:" + System.identityHashCode(this) + ")";
    }

    /**
     * Unmarshal entity.
     *
     * @param type the type of the entity to unmarshal
     * @param acceptedMediaType the accepted media type
     * @param in the input stream to unmarshal
     * @return the object
     * @throws JAXBException the JAXB exception
     */
    public Object unmarshalEntity(String type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
        if (JPARSLogger.isLoggableFinest(getSessionLog())) {
            in = in.markSupported() ? in : new BufferedInputStream(in);
            // TODO: Make readlimit configurable. Some http servers allow http post size to be unlimited.
            // If this is the case and if an application is sending huge post requests while jpars log
            // level configured to finest, this readlimit might not be sufficient.
            in.mark(52428800); // (~50MB)
            JPARSLogger.entering(getSessionLog(), CLASS_NAME, "unmarshalEntity", in);
        }
        Object unmarshalled = unmarshal(getClass(type), acceptedMediaType, in);
        JPARSLogger.exiting(getSessionLog(), CLASS_NAME, "unmarshalEntity", new Object[] { unmarshalled.getClass().getName(), unmarshalled });
        return unmarshalled;
    }

    /**
     * Unmarshal.
     *
     * @param type the type of the entity to unmarshal
     * @param acceptedMediaType the accepted media type
     * @param in the input stream to unmarshal
     * @return the object
     * @throws JAXBException the JAXB exception
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    public Object unmarshal(Class type, MediaType acceptedMediaType, InputStream in) throws JAXBException {
        Unmarshaller unmarshaller = getJAXBContext().createUnmarshaller();
        unmarshaller.setProperty(UnmarshallerProperties.JSON_INCLUDE_ROOT, Boolean.FALSE);
        unmarshaller.setProperty(UnmarshallerProperties.MEDIA_TYPE, acceptedMediaType.toString());
        unmarshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
        unmarshaller.setEventHandler(new ValidationEventHandler() {
            @Override
            /*
             * ReferenceAdaptor unmarshal throws exception if the object referred by a link
             * doesn't exist, and this handler is required to interrupt the unmarshal
             * operation under this condition.
             * (non-Javadoc) @see jakarta.xml.bind.ValidationEventHandler#handleEvent(jakarta.xml.bind.ValidationEvent)
             *
             */
            public boolean handleEvent(ValidationEvent event) {
                if (event.getSeverity() != ValidationEvent.WARNING) {
                    // ValidationEventLocator eventLocator = event.getLocator();
                    // Throwable throwable = event.getLinkedException();
                    // nothing is really useful to check for us in eventLocator
                    // and linked exception, just return false;
                    return false;
                }
                return true;
            }
        });

        for (XmlAdapter adapter : getAdapters()) {
            unmarshaller.setAdapter(adapter);
        }

        if (acceptedMediaType == MediaType.APPLICATION_JSON_TYPE) {
            // Part of the fix for https://bugs.eclipse.org/bugs/show_bug.cgi?id=394059
            // This issue happens when request has objects derived from an abstract class.
            // JSON_INCLUDE_ROOT is set to false for  JPA-RS. This means JSON requests won't have root tag.
            // The unmarshal method needs to be called with type, so that moxy can unmarshal the message based on type.
            // For xml, root tag is always set, unmarshaller must use root of the message for unmarshalling and type should
            // not be passed to unmarshal for xml type requests.
            JAXBElement<?> element = unmarshaller.unmarshal(new StreamSource(in), type);
            if (element.getValue() instanceof List<?>) {
                for (Object object : (List<?>) element.getValue()) {
                    wrap(object);
                }
                return element.getValue();
            } else {
                wrap(element.getValue());
            }
            return element.getValue();
        }

        Object domainObject = unmarshaller.unmarshal(new StreamSource(in));
        if (domainObject instanceof List<?>) {
            for (Object object : (List<?>) domainObject) {
                wrap(object);
            }
            return domainObject;
        } else {
            wrap(domainObject);
        }
        return domainObject;
    }

    /**
     * Make adjustments to an unmarshalled entity based on what is found in the weaved fields
     *
     */
    protected Object wrap(Object entity) {
        if ((entity != null) && (PersistenceWeavedRest.class.isAssignableFrom(entity.getClass()))) {
            if (!doesExist(null, entity)) {
                return entity;
            }
            ClassDescriptor descriptor = getJAXBDescriptorForClass(entity.getClass());
            if (entity instanceof FetchGroupTracker) {
                FetchGroup fetchGroup = new FetchGroup();
                for (DatabaseMapping mapping : descriptor.getMappings()) {
                    if (!(mapping instanceof XMLInverseReferenceMapping)) {
                        fetchGroup.addAttribute(mapping.getAttributeName());
                    }
                }
                (new FetchGroupManager()).setObjectFetchGroup(entity, fetchGroup, null);
                ((FetchGroupTracker) entity)._persistence_setSession(JpaHelper.getDatabaseSession(getEmf()));
            } else if (descriptor.hasRelationships()) {
                for (DatabaseMapping mapping : descriptor.getMappings()) {
                    if (mapping instanceof XMLInverseReferenceMapping) {
                        // we require Fetch groups to handle relationships
                        JPARSLogger.error(getSessionLog(), "weaving_required_for_relationships", new Object[] {});
                        throw JPARSException.invalidConfiguration();
                    }
                }
            }
        }
        return entity;
    }

    /**
     * Marshall an entity to either JSON or XML
     * Calling this method, will treat relationships as unfetched in the XML/JSON and marshall them as links
     * rather than attempting to marshall the data in those relationships
     */
    public void marshallEntity(Object object, MediaType mediaType, OutputStream output) throws JAXBException {
        JPARSLogger.entering(getSessionLog(), CLASS_NAME, "marshallEntity", new Object[] { object, mediaType });
        marshall(object, mediaType, output, true);
        JPARSLogger.exiting(getSessionLog(), CLASS_NAME, "marshallEntity", this, object, mediaType);
    }

    /**
     * Marshall an entity to either JSON or XML.
     *
     * @param object the object to marshal.
     * @param filter the filter (included/excluded fields) to use.
     * @param mediaType the media type (XML/JSON).
     * @param output the result.
     */
    public void marshallEntity(Object object, FieldsFilter filter, MediaType mediaType, OutputStream output) throws JAXBException {
        JPARSLogger.entering(getSessionLog(), CLASS_NAME, "marshallEntity", new Object[] { object, filter, mediaType });
        marshall(object, mediaType, output, true, filter);
        JPARSLogger.exiting(getSessionLog(), CLASS_NAME, "marshallEntity", this, object, mediaType);
    }

    /**
     * Marshall an entity to either JSON or XML.
     *
     * @param sendRelationships if this is set to true, relationships will be sent as links instead of sending.
     * the actual objects in the relationships
     */
    public void marshall(Object object, MediaType mediaType, OutputStream output, boolean sendRelationships) throws JAXBException {
        marshall(object, mediaType, output, sendRelationships, null);
    }

    /**
     * Marshall an entity to either JSON or XML.
     *
     * @param object the object to marshal.
     * @param mediaType the media type (XML/JSON).
     * @param output the result.
     * @param sendRelationships if this is set to true, relationships will be sent as links instead of sending
     *                          the actual objects in the relationships.
     * @param fieldsFilter      Specifies fields to include/exclude from the response.
     */
    @SuppressWarnings({"unchecked"})
    public void marshall(final Object object, final MediaType mediaType, final OutputStream output, boolean sendRelationships, final FieldsFilter fieldsFilter) throws JAXBException {
        if (version.compareTo(ServiceVersion.VERSION_2_0) < 0 && sendRelationships) {
            preMarshallEntity(object);
        }

        final Marshaller marshaller = getJAXBContext().createMarshaller();
        marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, mediaType.toString());
        marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
        marshaller.setProperty(MarshallerProperties.JSON_REDUCE_ANY_ARRAYS, true);
        marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);

        marshaller.setAdapter(new LinkAdapter(getBaseURI().toString(), this));
        marshaller.setAdapter(new RelationshipLinkAdapter(getBaseURI().toString(), this));

        for (XmlAdapter<?, ?> adapter : getAdapters()) {
            marshaller.setAdapter(adapter);
        }

        // v2.0 and higher
        if (version.compareTo(ServiceVersion.VERSION_2_0) >= 0) {
            // Create proxies for collections
            getCollectionWrapperBuilder().wrapCollections(object);

            // Build object graph + fields filtering
            final ObjectGraphBuilder objectGraphBuilder = new ObjectGraphBuilder(this);
            final ObjectGraph objectGraph = objectGraphBuilder.createObjectGraph(object, fieldsFilter);
            if (objectGraph != null) {
                marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, objectGraph);
            }
        }

        if (mediaType == MediaType.APPLICATION_XML_TYPE && object instanceof List) {
            marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
            XMLOutputFactory outputFactory = XMLOutputFactory.newFactory();
            XMLStreamWriter writer;
            try {
                writer = outputFactory.createXMLStreamWriter(output);
                writer.writeStartDocument();
                writer.writeStartElement(ReservedWords.JPARS_LIST_GROUPING_NAME);
                for (Object o : (List<Object>) object) {
                    marshaller.marshal(o, writer);
                }
                writer.writeEndDocument();
                writer.flush();
                postMarshallEntity(object);
            } catch (Exception ex) {
                throw JPARSException.exceptionOccurred(ex);
            }
        } else {
            marshaller.marshal(object, output);
            if (version.compareTo(ServiceVersion.VERSION_2_0) < 0) {
                postMarshallEntity(object);
            }
        }
    }

    /**
     * Process an entity and add any additional data that needs to be added prior to marshalling
     * This method will both single entities and lists of entities
     */
    @SuppressWarnings("rawtypes")
    protected void preMarshallEntity(Object object) {
        if (object instanceof List) {
            for (Object o : ((List) object)) {
                preMarshallIndividualEntity(o);
            }
        } else {
            preMarshallIndividualEntity(object);
        }
    }

    /**
     * Add any data required prior to marshalling an entity to XML or JSON
     * In general, this will only affect fields that have been weaved into the object
     */
    @SuppressWarnings("rawtypes")
    protected void preMarshallIndividualEntity(Object entity) {
        if (entity instanceof ReportQueryResultListItem) {
            ReportQueryResultListItem item = (ReportQueryResultListItem) entity;
            for (JAXBElement field : item.getFields()) {
                // one or more fields in the MultiResultQueryListItem might be a domain object,
                // so, we need to set the relationshipInfo for those domain objects.
                setRelationshipInfo(field.getValue());
            }
        } else if (entity instanceof SingleResultQueryList) {
            SingleResultQueryList item = (SingleResultQueryList) entity;
            for (JAXBElement field : item.getFields()) {
                // one or more fields in the SingleResultQueryList might be a domain object,
                // so, we need to set the relationshipInfo for those domain objects.
                setRelationshipInfo(field.getValue());
            }
        } else if (entity instanceof ReportQueryResultList) {
            ReportQueryResultList list = (ReportQueryResultList) entity;
            for (ReportQueryResultListItem item : list.getItems()) {
                for (JAXBElement field : item.getFields()) {
                    // one or more fields in the MultiResultQueryList might be a domain object,
                    // so, we need to set the relationshipInfo for those domain objects.
                    setRelationshipInfo(field.getValue());
                }
            }
        } else if (entity instanceof ReadAllQueryResultCollection) {
            ReadAllQueryResultCollection list = (ReadAllQueryResultCollection) entity;
            List<Object> items = list.getItems();
            if ((items != null) && (!items.isEmpty())) {
                for (Object item : items) {
                    setRelationshipInfo(item);
                }
            }
        } else if (entity instanceof ReportQueryResultCollection) {
            ReportQueryResultCollection list = (ReportQueryResultCollection) entity;
            List<ReportQueryResultListItem> items = list.getItems();
            if ((items != null) && (!items.isEmpty())) {
                for (ReportQueryResultListItem item : items) {
                    setRelationshipInfo(item);
                }
            }
        } else {
            setRelationshipInfo(entity);
        }
    }

    private void setRelationshipInfo(Object entity) {
        if ((entity != null) && (entity instanceof PersistenceWeavedRest)) {
            ClassDescriptor descriptor = getServerSession().getClassDescriptor(entity.getClass());
            if (descriptor != null) {
                ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<>());
                for (DatabaseMapping mapping : descriptor.getMappings()) {
                    if (mapping.isForeignReferenceMapping()) {
                        ForeignReferenceMapping frMapping = (ForeignReferenceMapping) mapping;
                        RelationshipInfo info = new RelationshipInfo();
                        info.setAttributeName(frMapping.getAttributeName());
                        info.setOwningEntity(entity);
                        info.setOwningEntityAlias(descriptor.getAlias());
                        info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
                        ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
                    } else if (mapping.isEISMapping()) {
                        if (mapping instanceof EISCompositeCollectionMapping) {
                            EISCompositeCollectionMapping eisMapping = (EISCompositeCollectionMapping) mapping;
                            RelationshipInfo info = new RelationshipInfo();
                            info.setAttributeName(eisMapping.getAttributeName());
                            info.setOwningEntity(entity);
                            info.setOwningEntityAlias(descriptor.getAlias());
                            info.setPersistencePrimaryKey(descriptor.getObjectBuilder().extractPrimaryKeyFromObject(entity, (AbstractSession) getServerSession()));
                            ((PersistenceWeavedRest) entity)._persistence_getRelationships().add(info);
                        }
                    }
                }
            }
        }
    }

    @SuppressWarnings("rawtypes")
    protected void postMarshallEntity(Object object) {
        if (object instanceof List) {
            for (Object entity : ((List) object)) {
                if (entity instanceof PersistenceWeavedRest) {
                    ((PersistenceWeavedRest) entity)._persistence_setRelationships(new ArrayList<>());
                }
            }
        } else if (object instanceof PersistenceWeavedRest) {
            ((PersistenceWeavedRest) object)._persistence_setRelationships(new ArrayList<>());
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected List<XmlAdapter<?, ?>> getAdapters() throws JPARSException {
        if (adapters != null) {
            return adapters;
        }
        adapters = new ArrayList<>();
        try {
            final ClassLoader cl = getServerSession().getDatasourcePlatform().getConversionManager().getLoader();

            for (ClassDescriptor desc : this.getServerSession().getDescriptors().values()) {
                if (version.compareTo(ServiceVersion.VERSION_2_0) >= 0) {
                    // Version is 2.0 or higher
                    // Collection adapter
                    final String collectionAdapterName = RestCollectionAdapterClassWriter.getClassName(desc.getJavaClass().getName());
                    final Class collectionAdaptorClass = Class.forName(collectionAdapterName, true, cl);
                    final Class[] argTypes = {PersistenceContext.class};
                    final Constructor collectionAdaptorConstructor = collectionAdaptorClass.getDeclaredConstructor(argTypes);
                    final Object[] args = new Object[]{this};
                    adapters.add((XmlAdapter) collectionAdaptorConstructor.newInstance(args));

                    // Reference adapter
                    final String refAdapterName = RestReferenceAdapterV2ClassWriter.getClassName(desc.getJavaClass().getName());
                    final Class refAdaptorClass = Class.forName(refAdapterName, true, cl);
                    final Class[] refAdapterTypes = {PersistenceContext.class};
                    final Constructor refAdaptorConstructor = refAdaptorClass.getDeclaredConstructor(refAdapterTypes);
                    final Object[] refAdapterArgs = new Object[]{this};
                    adapters.add((XmlAdapter) refAdaptorConstructor.newInstance(refAdapterArgs));
                } else {
                    // Version is 1.0 or below
                    // avoid embeddables
                    if (!desc.isAggregateCollectionDescriptor() && !desc.isAggregateDescriptor()) {
                        Class clz = desc.getJavaClass();
                        String referenceAdapterName = RestAdapterClassWriter.constructClassNameForReferenceAdapter(clz.getName());
                        Class referenceAdaptorClass = Class.forName(referenceAdapterName, true, cl);
                        Class[] argTypes1 = {String.class, PersistenceContext.class};
                        Constructor referenceAdaptorConstructor = referenceAdaptorClass.getDeclaredConstructor(argTypes1);
                        Object[] args1 = new Object[]{getBaseURI().toString(), this};
                        adapters.add((XmlAdapter) referenceAdaptorConstructor.newInstance(args1));
                    }
                }
            }
        } catch (RuntimeException | ReflectiveOperationException ex) {
            ex.printStackTrace();
            throw JPARSException.exceptionOccurred(ex);
        }
        return adapters;
    }

    private boolean getWeavingProperty() {
        // Initialize the properties with their defaults first
        boolean restWeavingEnabled = true;
        boolean fetchGroupWeavingEnabled = true;
        boolean weavingEnabled = true;

        Map<String, Object> properties = this.emf.getProperties();

        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();

            if (key.equals(PersistenceUnitProperties.WEAVING)) {
                if (!("true".equalsIgnoreCase((String) value)) && !("static".equalsIgnoreCase((String) value))) {
                    weavingEnabled = false;
                }
            }

            if (key.equals(PersistenceUnitProperties.WEAVING_REST)) {
                if (!("true".equalsIgnoreCase((String) value))) {
                    restWeavingEnabled = false;
                }
            }

            if (key.equals(PersistenceUnitProperties.WEAVING_FETCHGROUPS)) {
                if (!("true".equalsIgnoreCase((String) value))) {
                    fetchGroupWeavingEnabled = false;
                }
            }
        }
        return (weavingEnabled && restWeavingEnabled && fetchGroupWeavingEnabled);
    }

    /**
     * Gets the supported feature set.
     *
     * @return the supported feature set.
     */
    public FeatureSet getSupportedFeatureSet() {
        return version.getFeatureSet();
    }

    /**
     * Finds out is given query pageable or not.
     *
     * @param queryName named query to check.
     * @return true if pageable, false if not.
     */
    public boolean isQueryPageable(String queryName) {
        return getPageableQueries().get(queryName) != null;
    }

    /**
     * Gets REST pageable query details by query name.
     *
     * @param queryName named query name.
     * @return RestPageableQuery or null if query couldn't be found.
     */
    public RestPageableQuery getPageableQuery(String queryName) {
        return getPageableQueries().get(queryName);
    }

    /**
     * Sets the version.
     *
     * @param version the new version.
     */
    public void setVersion(String version) {
        this.version = ServiceVersion.fromCode(version);
    }

    /**
     * Sets the base uri.
     *
     * @param baseURI the new base uri
     */
    public void setBaseURI(URI baseURI) {
        this.baseURI = baseURI;
    }

    /**
     * Getter for pageableQueries property with lazy initialization.
     *
     * @return The initialized pageableQueries property.
     */
    private Map<String, RestPageableQuery> getPageableQueries() {
        // Lazy initialization
        if (pageableQueries == null) {
            initPageableQueries();
        }

        return pageableQueries;
    }

    /**
     * Initializes pageableQueries map by reading RestPageableQueries entity annotations.
     */
    private void initPageableQueries() {
        pageableQueries = new HashMap<>();

        // Iterate on all entity classes
        for (Class<?> clazz : getServerSession().getProject().getDescriptors().keySet()) {
            if (clazz.isAnnotationPresent(RestPageableQueries.class)) {
                final RestPageableQueries restPageableQueries = clazz.getAnnotation(RestPageableQueries.class);

                // Process each RestPageableQuery annotation in the list
                for (RestPageableQuery restPageableQuery : restPageableQueries.value()) {
                    pageableQueries.put(restPageableQuery.queryName(), restPageableQuery);
                }
            }
        }
    }

    /**
     * Getter for the collectionWrapperBuilder property with lazy initialization.
     *
     * @return the collectionWrapperBuilder.
     */
    private CollectionWrapperBuilder getCollectionWrapperBuilder() {
        if (collectionWrapperBuilder == null) {
            collectionWrapperBuilder = new CollectionWrapperBuilder(this);
        }
        return collectionWrapperBuilder;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((version == null) ? 0 : version.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }

        if (other == null) {
            return false;
        }

        if (getClass() != other.getClass()) {
            return false;
        }

        PersistenceContext otherContext = (PersistenceContext) other;

        if (name == null) {
            if (otherContext.name != null) {
                return false;
            }
        } else if (!name.equals(otherContext.name)) {
            return false;
        }

        if (version == null) {
            if (otherContext.version != null) {
                return false;
            }
        } else if (!version.equals(otherContext.version)) {
            return false;
        }

        return true;
    }
}
