/*
 * Copyright (c) 2011, 2020 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:
//      gonural - Initial implementation
//      2014-09-01-2.6.0 Dmitry Kornilov
//        - JPARS v2.0 related changes
package org.eclipse.persistence.jpa.rs.resources.common;

import static org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller.mediaType;

import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import jakarta.persistence.EntityManager;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.ResponseBuilder;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.RelationalDescriptor;
import org.eclipse.persistence.expressions.Expression;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.QueryParameters;
import org.eclipse.persistence.jpa.rs.exceptions.JPARSException;
import org.eclipse.persistence.jpa.rs.features.FeatureResponseBuilder;
import org.eclipse.persistence.jpa.rs.features.FeatureSet;
import org.eclipse.persistence.jpa.rs.features.FeatureSet.Feature;
import org.eclipse.persistence.jpa.rs.features.ServiceVersion;
import org.eclipse.persistence.jpa.rs.features.fieldsfiltering.FieldsFilter;
import org.eclipse.persistence.jpa.rs.features.fieldsfiltering.FieldsFilteringValidator;
import org.eclipse.persistence.jpa.rs.features.paging.PageableFieldValidator;
import org.eclipse.persistence.jpa.rs.util.HrefHelper;
import org.eclipse.persistence.jpa.rs.util.IdHelper;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DatabaseMapping.WriteType;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.queries.ReadQuery;
import org.eclipse.persistence.sessions.DatabaseSession;

/**
 * Base class for entity resource.
 *
 * @author gonural
 */
public abstract class AbstractEntityResource extends AbstractResource {
    private static final String CLASS_NAME = AbstractEntityResource.class.getName();

    protected Response findAttributeInternal(String version, String persistenceUnit, String type, String id, String attribute, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "findAttributeInternal", new Object[] { "GET", version, persistenceUnit, type, id, attribute, uriInfo.getRequestUri().toASCIIString() });

        EntityManager em = null;
        try {
            PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            Object entityId = IdHelper.buildId(context, type, id);
            em = context.getEmf().createEntityManager(getMatrixParameters(uriInfo, persistenceUnit));

            Object entity = em.find(context.getClass(type), entityId, getQueryParameters(uriInfo));
            DatabaseSession serverSession = context.getServerSession();
            ClassDescriptor descriptor = serverSession.getClassDescriptor(context.getClass(type));
            if (descriptor == null) {
                throw JPARSException.classOrClassDescriptorCouldNotBeFoundForEntity(type, persistenceUnit);
            }

            DatabaseMapping attributeMapping = descriptor.getMappingForAttributeName(attribute);
            if ((attributeMapping == null) || (entity == null)) {
                throw JPARSException.databaseMappingCouldNotBeFoundForEntityAttribute(attribute, type, id, persistenceUnit);
            }

            if (!attributeMapping.isCollectionMapping()) {
                Object result = attributeMapping.getRealAttributeValueFromAttribute(attributeMapping.getAttributeValueFromObject(entity), entity, (AbstractSession) serverSession);
                if (result == null) {
                    JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_entity_for_attribute", new Object[] { attribute, type, id, persistenceUnit });
                    throw JPARSException.attributeCouldNotBeFoundForEntity(attribute, type, id, persistenceUnit);
                }
                final FeatureResponseBuilder responseBuilder = context.getSupportedFeatureSet().getResponseBuilder(Feature.NO_PAGING);
                return findAttributeResponse(context, attribute, type, id, persistenceUnit, result, getQueryParameters(uriInfo), headers, uriInfo, responseBuilder, null);
            }

            ReadQuery query = (ReadQuery) ((((ForeignReferenceMapping) attributeMapping).getSelectionQuery()).clone());
            if (query == null) {
                throw JPARSException.selectionQueryForAttributeCouldNotBeFoundForEntity(attribute, type, id, persistenceUnit);
            }

            final FeatureSet featureSet = context.getSupportedFeatureSet();
            final AbstractSession clientSession = context.getClientSession(em);

            // Fields filtering
            FieldsFilter fieldsFilter = null;
            if (context.getSupportedFeatureSet().isSupported(Feature.FIELDS_FILTERING)) {
                final FieldsFilteringValidator fieldsFilteringValidator = new FieldsFilteringValidator(uriInfo);
                if (fieldsFilteringValidator.isFeatureApplicable()) {
                    fieldsFilter = fieldsFilteringValidator.getFilter();
                }
            }

            // Pagination
            if (featureSet.isSupported(Feature.PAGING)) {
                final PageableFieldValidator validator = new PageableFieldValidator(entity.getClass(), attribute, uriInfo);
                if (validator.isFeatureApplicable()) {
                    // Adding extra one to detect are there more rows or not. It will be removed later
                    // on in response processor.
                    query.setMaxRows(validator.getLimit() + validator.getOffset() + 1);
                    query.setFirstResult(validator.getOffset());

                    // We need to add limit and offset to query parameters because request builder reads it from there
                    final Map<String, Object> queryParams = getQueryParameters(uriInfo);
                    queryParams.put(QueryParameters.JPARS_PAGING_LIMIT, String.valueOf(validator.getLimit()));
                    queryParams.put(QueryParameters.JPARS_PAGING_OFFSET, String.valueOf(validator.getOffset()));

                    // check orderBy, and generate a warning if there is none
                    checkOrderBy(context, query);

                    final Object result = clientSession.executeQuery(query, descriptor.getObjectBuilder().buildRow(entity, clientSession, WriteType.INSERT));
                    final FeatureResponseBuilder responseBuilder = context.getSupportedFeatureSet().getResponseBuilder(Feature.PAGING);
                    return findAttributeResponse(context, attribute, type, id, persistenceUnit, result, queryParams, headers, uriInfo, responseBuilder, fieldsFilter);
                }
            }

            final Object result = clientSession.executeQuery(query, descriptor.getObjectBuilder().buildRow(entity, clientSession, WriteType.INSERT));
            final FeatureResponseBuilder responseBuilder = context.getSupportedFeatureSet().getResponseBuilder(Feature.NO_PAGING);
            return findAttributeResponse(context, attribute, type, id, persistenceUnit, result, getQueryParameters(uriInfo), headers, uriInfo, responseBuilder, fieldsFilter);
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        } finally {
            if (em != null) {
                if (em.isOpen()) {
                    em.close();
                }
            }
        }
    }

    protected Response findInternal(String version, String persistenceUnit, String type, String id, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "findInternal", new Object[] { "GET", version, persistenceUnit, type, id, uriInfo.getRequestUri().toASCIIString() });

        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            final Map<String, String> discriminators = getMatrixParameters(uriInfo, persistenceUnit);
            final Object entityId = IdHelper.buildId(context, type, id);
            final Object entity = context.find(discriminators, type, entityId, getQueryParameters(uriInfo));
            if (entity == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_entity_for_key", new Object[] { type, id, persistenceUnit });
                throw JPARSException.entityNotFound(type, id, persistenceUnit);
            }

            // Fields filtering
            if (context.getSupportedFeatureSet().isSupported(Feature.FIELDS_FILTERING)) {
                final FieldsFilteringValidator fieldsFilteringValidator = new FieldsFilteringValidator(uriInfo);
                if (fieldsFilteringValidator.isFeatureApplicable()) {
                    final StreamingOutputMarshaller marshaller = new StreamingOutputMarshaller(context,
                            singleEntityResponse(context, entity, uriInfo),
                            headers.getAcceptableMediaTypes(),
                            fieldsFilteringValidator.getFilter());
                    return Response.ok(marshaller).build();
                }
            }

            return Response.ok(new StreamingOutputMarshaller(context, singleEntityResponse(context, entity, uriInfo), headers.getAcceptableMediaTypes())).build();
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    protected Response createInternal(String version, String persistenceUnit, String type, HttpHeaders headers, UriInfo uriInfo, InputStream in) {
        JPARSLogger.entering(CLASS_NAME, "createInternal", new Object[] { "PUT", headers.getMediaType(), version, persistenceUnit, type, uriInfo.getRequestUri().toASCIIString() });
        try {
            final PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            final ClassDescriptor descriptor = context.getDescriptor(type);
            if (descriptor == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
                throw JPARSException.classOrClassDescriptorCouldNotBeFoundForEntity(type, persistenceUnit);
            }

            final Object entity = context.unmarshalEntity(type, mediaType(headers.getAcceptableMediaTypes()), in);

            // Check idempotence of the entity
            if (!checkIdempotence(descriptor, entity)) {
                JPARSLogger.error(context.getSessionLog(), "jpars_put_not_idempotent", new Object[]{type, persistenceUnit});
                throw JPARSException.entityIsNotIdempotent(type, persistenceUnit);
            }

            // Check idempotence of the entity's relationships
            if (!checkIdempotenceOnRelationships(descriptor, entity)) {
                JPARSLogger.error(context.getSessionLog(), "jpars_put_not_idempotent", new Object[]{type, persistenceUnit});
                throw JPARSException.entityIsNotIdempotent(type, persistenceUnit);
            }

            // Cascade persist. Sets references to the parent object in collections with objects passed by value.
            if (context.getServiceVersion().compareTo(ServiceVersion.VERSION_2_0) >= 0) {
                processBidirectionalRelationships(context, descriptor, entity);
            }

            // No sequencing in relationships, we can create the object now...
            context.create(getMatrixParameters(uriInfo, persistenceUnit), entity);
            final ResponseBuilder rb = Response.status(Status.CREATED);
            return rb.entity(new StreamingOutputMarshaller(context, singleEntityResponse(context, entity, uriInfo), headers.getAcceptableMediaTypes())).build();
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    /**
     * Finds all bidirectional relationships of the given entity with Cascade=PERSIST and sets reference to the parent
     * object.
     * This method is called on creating new entities in JPARS v2.0 only.
     *
     * @param context       the persistence context.
     * @param descriptor    descriptor of the entity passed in 'entity' parameter.
     * @param entity        entity to process.
     */
    private void processBidirectionalRelationships(PersistenceContext context, ClassDescriptor descriptor, Object entity) {
        final List<DatabaseMapping> mappings = descriptor.getMappings();
        for (DatabaseMapping mapping : mappings) {
            if ((mapping != null) && (mapping instanceof ForeignReferenceMapping)) {
                final ForeignReferenceMapping jpaMapping = (ForeignReferenceMapping) mapping;
                final Object attributeValue = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
                if (jpaMapping.isCascadePersist()) {
                    if (jpaMapping.getMappedBy() != null) {
                        final ClassDescriptor inverseDescriptor = context.getDescriptor(jpaMapping.getReferenceDescriptor().getAlias());
                        if (inverseDescriptor != null) {
                            final DatabaseMapping inverseMapping = inverseDescriptor.getMappingForAttributeName(jpaMapping.getMappedBy());
                            if (inverseMapping != null) {
                                if (attributeValue != null) {
                                    if (attributeValue instanceof ValueHolder) {
                                        final ValueHolder holder = (ValueHolder) attributeValue;
                                        final Object obj = holder.getValue();
                                        if (obj != null) {
                                            inverseMapping.setAttributeValueInObject(obj, entity);
                                        }
                                    } else if (attributeValue instanceof Collection) {
                                        final Collection<?> collection = (Collection<?>) attributeValue;
                                        if (!collection.isEmpty()) {
                                            for (Object obj : collection) {
                                                inverseMapping.setAttributeValueInObject(obj, entity);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * This method maintains idempotence on PUT by disallowing sequencing in relationships.
     *
     * @param descriptor    descriptor of the entity passed in 'entity' parameter.
     * @param entity        entity to process.
     * @return true if check is passed (no sequencing)
     */
    private boolean checkIdempotenceOnRelationships(ClassDescriptor descriptor, Object entity) {
        final List<DatabaseMapping> mappings = descriptor.getMappings();
        if ((mappings != null) && (!mappings.isEmpty())) {
            for (DatabaseMapping mapping : mappings) {
                if (mapping instanceof ForeignReferenceMapping) {
                    final ForeignReferenceMapping fkMapping = (ForeignReferenceMapping) mapping;
                    if ((fkMapping.isCascadePersist()) || (fkMapping.isCascadeMerge())) {
                        final ClassDescriptor referenceDescriptor = fkMapping.getReferenceDescriptor();
                        if (referenceDescriptor != null) {
                            if (referenceDescriptor instanceof RelationalDescriptor) {
                                final RelationalDescriptor relDesc = (RelationalDescriptor) referenceDescriptor;
                                final AbstractDirectMapping relSequenceMapping = relDesc.getObjectBuilder().getSequenceMapping();
                                if (relSequenceMapping != null) {
                                    final Object value = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
                                    if (value != null) {
                                        if (value instanceof ValueHolder) {
                                            final ValueHolder holder = (ValueHolder) value;
                                            if (holder.getValue() != null) {
                                                return false;
                                            }
                                        } else if (value instanceof Collection) {
                                            if (!(((Collection<?>) value).isEmpty())) {
                                                return false;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return true;
    }

    /**
     * This method maintains idempotence on PUT by disallowing sequencing.
     *
     * @param descriptor    descriptor of the entity passed in 'entity' parameter.
     * @param entity        entity to process.
     * @return true if check is passed (no sequencing)
     */
    private boolean checkIdempotence(ClassDescriptor descriptor, Object entity) {
        final AbstractDirectMapping sequenceMapping = descriptor.getObjectBuilder().getSequenceMapping();
        if (sequenceMapping != null) {
            final Object value = sequenceMapping.getAttributeAccessor().getAttributeValueFromObject(entity);
            if (descriptor.getObjectBuilder().isPrimaryKeyComponentInvalid(value, descriptor.getPrimaryKeyFields().indexOf(descriptor.getSequenceNumberField()))
                    || descriptor.getSequence().shouldAlwaysOverrideExistingValue()) {
                return false;
            }
        }
        return true;
    }

    protected Response updateInternal(String version, String persistenceUnit, String type, HttpHeaders headers, UriInfo uriInfo, InputStream in) {
        JPARSLogger.entering(CLASS_NAME, "updateInternal", new Object[] { "POST", headers.getMediaType(), version, persistenceUnit, type, uriInfo.getRequestUri().toASCIIString() });
        try {
            PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            Object entity = context.unmarshalEntity(type, mediaType(headers.getAcceptableMediaTypes()), in);
            entity = context.merge(getMatrixParameters(uriInfo, persistenceUnit), entity);
            return Response.ok(new StreamingOutputMarshaller(context, singleEntityResponse(context, entity, uriInfo), headers.getAcceptableMediaTypes())).build();
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    protected Response setOrAddAttributeInternal(String version, String persistenceUnit, String type, String id, String attribute, HttpHeaders headers, UriInfo uriInfo, InputStream in) {
        JPARSLogger.entering(CLASS_NAME, "setOrAddAttributeInternal", new Object[] { "POST", headers.getMediaType(), version, persistenceUnit, type, id, attribute, uriInfo.getRequestUri().toASCIIString() });
        try {
            PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            Object entityId = IdHelper.buildId(context, type, id);
            String partner = getRelationshipPartner(getMatrixParameters(uriInfo, attribute), getQueryParameters(uriInfo));
            ClassDescriptor descriptor = context.getDescriptor(type);
            DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
            if (!mapping.isForeignReferenceMapping()) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_appropriate_mapping_for_update", new Object[] { attribute, type, id, persistenceUnit });
                throw JPARSException.databaseMappingCouldNotBeFoundForEntityAttribute(attribute, type, id, persistenceUnit);
            }
            Object entity = context.unmarshalEntity(mapping.getReferenceDescriptor().getAlias(), mediaType(headers.getAcceptableMediaTypes()), in);
            Object result = context.updateOrAddAttribute(getMatrixParameters(uriInfo, persistenceUnit), type, entityId, getQueryParameters(uriInfo), attribute, entity, partner);
            if (result == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_update_attribute", new Object[] { attribute, type, id, persistenceUnit });
                throw JPARSException.attributeCouldNotBeUpdated(attribute, type, id, persistenceUnit);
            }
            return Response.ok(new StreamingOutputMarshaller(context, singleEntityResponse(context, result, uriInfo), headers.getAcceptableMediaTypes())).build();
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    protected Response removeAttributeInternal(String version, String persistenceUnit, String type, String id, String attribute, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "removeAttributeInternal", new Object[] { "DELETE", headers.getMediaType(), version, persistenceUnit, type, id, attribute, uriInfo.getRequestUri().toASCIIString() });
        try {
            String listItemId = null;
            Map<String, String> matrixParams = getMatrixParameters(uriInfo, attribute);
            Map<String, Object> queryParams = getQueryParameters(uriInfo);

            if ((queryParams != null) && (!queryParams.isEmpty())) {
                listItemId = (String) queryParams.get(QueryParameters.JPARS_LIST_ITEM_ID);
            }

            if ((attribute == null) && (listItemId == null)) {
                throw JPARSException.invalidRemoveAttributeRequest(null, type, id, persistenceUnit);
            }

            String partner = getRelationshipPartner(matrixParams, queryParams);
            PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            Object entityId = IdHelper.buildId(context, type, id);
            ClassDescriptor descriptor = context.getDescriptor(type);
            DatabaseMapping mapping = descriptor.getMappingForAttributeName(attribute);
            if (!mapping.isForeignReferenceMapping()) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_appropriate_mapping_for_update", new Object[] { attribute, type, id, persistenceUnit });
                throw JPARSException.databaseMappingCouldNotBeFoundForEntityAttribute(attribute, type, id, persistenceUnit);
            }

            Map<String, String> discriminators = getMatrixParameters(uriInfo, persistenceUnit);
            Object entity = context.find(discriminators, type, entityId, getQueryParameters(uriInfo));
            Object result = context.removeAttribute(getMatrixParameters(uriInfo, persistenceUnit), type, entityId, attribute, listItemId, entity, partner);

            if (result == null) {
                JPARSLogger.error(context.getSessionLog(), "jpars_could_not_update_attribute", new Object[] { attribute, type, id, persistenceUnit });
                throw JPARSException.attributeCouldNotBeUpdated(attribute, type, id, persistenceUnit);
            } else {
                return Response.ok(new StreamingOutputMarshaller(context, singleEntityResponse(context, result, uriInfo), headers.getAcceptableMediaTypes())).build();
            }
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    protected Response deleteInternal(String version, String persistenceUnit, String type, String id, HttpHeaders headers, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "deleteInternal", new Object[] { "DELETE", headers.getMediaType(), version, persistenceUnit, type, id, uriInfo.getRequestUri().toASCIIString() });
        try {
            PersistenceContext context = getPersistenceContext(persistenceUnit, type, uriInfo.getBaseUri(), version, null);
            Map<String, String> discriminators = getMatrixParameters(uriInfo, persistenceUnit);
            Object entityId = IdHelper.buildId(context, type, id);
            context.delete(discriminators, type, entityId);
            return Response.ok().build();
        } catch (Exception ex) {
            throw JPARSException.exceptionOccurred(ex);
        }
    }

    protected Response buildEntityOptionsResponse(String version, String persistenceUnit, String entityName, HttpHeaders httpHeaders, UriInfo uriInfo) {
        JPARSLogger.entering(CLASS_NAME, "buildEntityOptionsResponse", new Object[]{"GET", version, persistenceUnit, entityName, uriInfo.getRequestUri().toASCIIString()});
        final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);

        // We need to make sure that entity with given name exists
        final ClassDescriptor descriptor = context.getServerSession().getDescriptorForAlias(entityName);
        if (descriptor == null) {
            JPARSLogger.error(context.getSessionLog(), "jpars_could_not_find_entity_type", new Object[]{entityName, persistenceUnit});
            throw JPARSException.classOrClassDescriptorCouldNotBeFoundForEntity(entityName, persistenceUnit);
        }

        final String linkValue = "<" + HrefHelper.buildEntityMetadataHref(context, entityName) + ">; rel=describedby";
        httpHeaders.getRequestHeaders().putSingle("Link", linkValue);

        return Response.ok()
                .header("Link", linkValue)
                .build();
    }

    private Response findAttributeResponse(PersistenceContext context,
                                           String attribute,
                                           String entityType,
                                           String id,
                                           String persistenceUnit,
                                           Object queryResults,
                                           Map<String, Object> queryParams,
                                           HttpHeaders headers, UriInfo uriInfo,
                                           FeatureResponseBuilder responseBuilder,
                                           FieldsFilter filter) {
        if (queryResults != null) {
            Object results = responseBuilder.buildAttributeResponse(context, queryParams, attribute, queryResults, uriInfo);
            if (results != null) {
                return Response.ok(new StreamingOutputMarshaller(context, results, headers.getAcceptableMediaTypes(), filter)).build();
            } else {
                // something is wrong with the descriptors
                throw JPARSException.responseCouldNotBeBuiltForFindAttributeRequest(attribute, entityType, id, persistenceUnit);
            }
        }
        return Response.ok(new StreamingOutputMarshaller(context, null, headers.getAcceptableMediaTypes(), filter)).build();
    }

    private void checkOrderBy(PersistenceContext context, ReadQuery query) {
        if (query.isReadAllQuery()) {
            ReadAllQuery readAllQuery = (ReadAllQuery) query;
            List<Expression> orderBy = readAllQuery.getOrderByExpressions();
            if ((orderBy == null) || (orderBy.isEmpty())) {
                JPARSLogger.warning(context.getSessionLog(), "no_orderby_clause_for_paging", new Object[] { query.toString() });
            }
        }
    }

    private Object singleEntityResponse(PersistenceContext context, Object entity, UriInfo uriInfo) {
        FeatureSet featureSet = context.getSupportedFeatureSet();
        FeatureResponseBuilder responseBuilder = featureSet.getResponseBuilder(Feature.NO_PAGING);
        return responseBuilder.buildSingleEntityResponse(context, getQueryParameters(uriInfo), entity, uriInfo);
    }
}
