/*
 * 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.jaxb.metadata.MetadataSource;
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;

    protected TransactionWrapper transaction = null;

    private Boolean weavingEnabled = null;

    private ServiceVersion version = ServiceVersion.NO_VERSION;

    /** 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, EntityManagerFactoryImpl emf, URI defaultURI) {
        super();
        init(emfName, emf, defaultURI, ServiceVersion.NO_VERSION);
    }

    /**
     * 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, EntityManagerFactoryImpl emf, URI defaultURI, ServiceVersion version) {
        super();
        init(emfName, emf, defaultURI, version);
    }

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

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

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

        try {
            this.jaxbContext = createDynamicJAXBContext(emf.getDatabaseSession());
        } catch (JAXBException jaxbe) {
            JPARSLogger.exception(getSessionLog(), "exception_creating_jaxb_context", new Object[] { emfName, jaxbe.toString() }, jaxbe);
            emf.close();
        } catch (IOException e) {
            JPARSLogger.exception(getSessionLog(), "exception_creating_jaxb_context", new Object[] { emfName, e.toString() }, e);
            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, AbstractSession session) {
        Set<String> packages = new HashSet<String>();
        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(AbstractSession 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 EntityManagerFactoryImpl createEntityManagerFactory(PersistenceUnitInfo info, Map<String, ?> properties) {
        PersistenceProvider provider = new PersistenceProvider();
        EntityManagerFactory emf = provider.createContainerEntityManagerFactory(info, properties);
        return (EntityManagerFactoryImpl) 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
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    protected Map<String, Object> createJAXBProperties(AbstractSession session) throws IOException {
        Map<String, Object> properties = new HashMap<String, Object>(1);
        List<Object> metadataLocations = new ArrayList<Object>();

        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
        for (MetadataSource metadataSource : getSupportedFeatureSet().getMetadataSources()) {
            metadataLocations.add(metadataSource);
        }

        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();
        }
    }

    @SuppressWarnings("unchecked")
    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<Object>();
                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();
        }
    }

    @SuppressWarnings("rawtypes")
    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
     */
    @SuppressWarnings("rawtypes")
    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.
     */
    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<RelationshipInfo>());
                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<RelationshipInfo>());
                }
            }
        } else if (object instanceof PersistenceWeavedRest) {
            ((PersistenceWeavedRest) object)._persistence_setRelationships(new ArrayList<RelationshipInfo>());
        }
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    protected List<XmlAdapter<?, ?>> getAdapters() throws JPARSException {
        if (adapters != null) {
            return adapters;
        }
        adapters = new ArrayList<XmlAdapter<?, ?>>();
        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<String, RestPageableQuery>();

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