Package org.eclipse.persistence.jpa.rs.resources.common

Source Code of org.eclipse.persistence.jpa.rs.resources.common.AbstractEntityResource

/*******************************************************************************
* Copyright (c) 2011, 2013 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 v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
*
******************************************************************************/

package org.eclipse.persistence.jpa.rs.resources.common;

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

import java.io.InputStream;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.namespace.QName;

import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.RelationalDescriptor;
import org.eclipse.persistence.indirection.ValueHolder;
import org.eclipse.persistence.internal.weaving.PersistenceWeavedRest;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.QueryParameters;
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.jpa.rs.util.list.SimpleHomogeneousList;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.foundation.AbstractDirectMapping;

/**
* @author gonural
*
*/
public abstract class AbstractEntityResource extends AbstractResource {

    @SuppressWarnings({ "rawtypes" })
    protected Response findAttribute(String version, String persistenceUnit, String type, String key, String attribute, HttpHeaders hh, UriInfo ui, URI baseURI) {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }
        Map<String, String> discriminators = getMatrixParameters(ui, persistenceUnit);
        Object id = IdHelper.buildId(app, type, key);

        Object entity = app.findAttribute(discriminators, type, id, getQueryParameters(ui), attribute);

        if (entity == null) {
            JPARSLogger.fine("jpars_could_not_entity_for_attribute", new Object[] { type, key, attribute, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Boolean collectionContainsDomainObjects = collectionContainsDomainObjects(entity);
        if (collectionContainsDomainObjects != null) {
            if (collectionContainsDomainObjects.booleanValue()) {
                return Response.ok(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes())).build();
            } else {
                // Classes derived from PersistenceWeavedRest class are already in the JAXB context and marshalled properly.
                // Here, we will only need to deal with collection of classes that are not in the JAXB context, such as String, Integer...
                //
                // Jersey 1.2 introduced a new api JResponse to support this better, but in order to be able to work with
                // older versions of Jersey, we will use our own wrapper.
                return Response.ok(new StreamingOutputMarshaller(app, populateSimpleHomogeneousList((Collection) entity, attribute), hh.getAcceptableMediaTypes())).build();
            }
        }
        return Response.ok(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes())).build();
    }

    protected Response find(String version, String persistenceUnit, String type, String key, HttpHeaders hh, UriInfo ui, URI baseURI) {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }
        Map<String, String> discriminators = getMatrixParameters(ui, persistenceUnit);

        Object id = IdHelper.buildId(app, type, key);

        Object entity = app.find(discriminators, type, id, getQueryParameters(ui));

        if (entity == null) {
            JPARSLogger.fine("jpars_could_not_entity_for_key", new Object[] { type, key, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        } else {
            return Response.ok(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes())).build();
        }
    }

    @SuppressWarnings("rawtypes")
    protected Response create(String version, String persistenceUnit, String type, HttpHeaders hh, UriInfo uriInfo, URI baseURI, InputStream in) throws JAXBException {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null) {
            JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }
        ClassDescriptor descriptor = app.getDescriptor(type);
        if (descriptor == null) {
            JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }
        Object entity = null;
        try {
            entity = app.unmarshalEntity(type, mediaType(hh.getAcceptableMediaTypes()), in);
        } catch (JAXBException e) {
            JPARSLogger.fine("exception_while_unmarhalling_entity", new Object[] { type, persistenceUnit, e.toString() });
            return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        // maintain idempotence on PUT by disallowing sequencing
        AbstractDirectMapping sequenceMapping = descriptor.getObjectBuilder().getSequenceMapping();
        if (sequenceMapping != null) {
            Object value = sequenceMapping.getAttributeAccessor().getAttributeValueFromObject(entity);

            if (descriptor.getObjectBuilder().isPrimaryKeyComponentInvalid(value, descriptor.getPrimaryKeyFields().indexOf(descriptor.getSequenceNumberField()))
                    || descriptor.getSequence().shouldAlwaysOverrideExistingValue()) {
                JPARSLogger.fine("jpars_put_not_idempotent", new Object[] { type, persistenceUnit });
                return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
            }
        }

        // maintain idempotence on PUT by disallowing sequencing in relationships
        List<DatabaseMapping> mappings = descriptor.getMappings();
        if ((mappings != null) && (!mappings.isEmpty())) {
            for (DatabaseMapping mapping : mappings) {
                if (mapping instanceof ForeignReferenceMapping) {
                    ForeignReferenceMapping fkMapping = (ForeignReferenceMapping) mapping;
                    if ((fkMapping.isCascadePersist()) || (fkMapping.isCascadeMerge())) {
                        ClassDescriptor referenceDescriptor = fkMapping.getReferenceDescriptor();
                        if (referenceDescriptor != null) {
                            if (referenceDescriptor instanceof RelationalDescriptor) {
                                RelationalDescriptor relDesc = (RelationalDescriptor) referenceDescriptor;
                                AbstractDirectMapping relSequenceMapping = relDesc.getObjectBuilder().getSequenceMapping();
                                if (relSequenceMapping != null) {
                                    Object value = mapping.getAttributeAccessor().getAttributeValueFromObject(entity);
                                    if (value != null) {
                                        if (value instanceof ValueHolder) {
                                            ValueHolder holder = (ValueHolder) value;
                                            if (holder != null) {
                                                Object obj = holder.getValue();
                                                if (obj != null) {
                                                    JPARSLogger.fine("jpars_put_not_idempotent", new Object[] { type, persistenceUnit });
                                                    return Response.status(Status.BAD_REQUEST).build();
                                                }
                                            }
                                        } else if (value instanceof Collection) {
                                            if (!(((Collection) value).isEmpty())) {
                                                JPARSLogger.fine("jpars_put_not_idempotent", new Object[] { type, persistenceUnit });
                                                return Response.status(Status.BAD_REQUEST).build();
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        // No sequencing in relationships, we can create the object now...
        app.create(getMatrixParameters(uriInfo, persistenceUnit), entity);
        ResponseBuilder rb = Response.status(Status.CREATED);
        rb.entity(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes()));
        return rb.build();
    }

    protected Response update(String version, String persistenceUnit, String type, HttpHeaders hh, UriInfo uriInfo, URI baseURI, InputStream in) {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }
        Object entity = null;
        try {
            entity = app.unmarshalEntity(type, mediaType(hh.getAcceptableMediaTypes()), in);
        } catch (JAXBException e) {
            JPARSLogger.fine("exception_while_unmarhalling_entity", new Object[] { type, persistenceUnit, e.toString() });
            return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        entity = app.merge(getMatrixParameters(uriInfo, persistenceUnit), entity);
        return Response.ok(new StreamingOutputMarshaller(app, entity, hh.getAcceptableMediaTypes())).build();
    }

    protected Response setOrAddAttribute(String version, String persistenceUnit, String type, String key, String attribute, HttpHeaders hh, UriInfo ui, URI baseURI, InputStream in) {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Object id = IdHelper.buildId(app, type, key);

        Object entity = null;
        String partner = getRelationshipPartner(getMatrixParameters(ui, attribute), getQueryParameters(ui));
        try {
            ClassDescriptor descriptor = app.getDescriptor(type);
            DatabaseMapping mapping = (DatabaseMapping) descriptor.getMappingForAttributeName(attribute);
            if (!mapping.isForeignReferenceMapping()) {
                JPARSLogger.fine("jpars_could_find_appropriate_mapping_for_update", new Object[] { attribute, type, key, persistenceUnit });
                return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
            }
            entity = app.unmarshalEntity(((ForeignReferenceMapping) mapping).getReferenceDescriptor().getAlias(), mediaType(hh.getAcceptableMediaTypes()), in);
        } catch (JAXBException e) {
            JPARSLogger.fine("exception_while_unmarhalling_entity", new Object[] { type, persistenceUnit, e.toString() });
            return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Object result = app.updateOrAddAttribute(getMatrixParameters(ui, persistenceUnit), type, id, getQueryParameters(ui), attribute, entity, partner);

        if (result == null) {
            JPARSLogger.fine("jpars_could_not_update_attribute", new Object[] { attribute, type, key, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        } else {
            return Response.ok(new StreamingOutputMarshaller(app, result, hh.getAcceptableMediaTypes())).build();
        }
    }

    protected Response removeAttributeInternal(String version, String persistenceUnit, String type, String key, String attribute, HttpHeaders hh, UriInfo ui) {
        String listItemId = null;
        Map<String, String> matrixParams = getMatrixParameters(ui, attribute);
        Map<String, Object> queryParams = getQueryParameters(ui);

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

        String partner = getRelationshipPartner(matrixParams, queryParams);

        PersistenceContext app = getPersistenceContext(persistenceUnit, ui.getBaseUri(), version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        if ((attribute == null) && (listItemId == null)) {
            return Response.status(Status.BAD_REQUEST).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Object id = IdHelper.buildId(app, type, key);

        ClassDescriptor descriptor = app.getDescriptor(type);
        DatabaseMapping mapping = (DatabaseMapping) descriptor.getMappingForAttributeName(attribute);
        if (!mapping.isForeignReferenceMapping()) {
            JPARSLogger.fine("jpars_could_find_appropriate_mapping_for_update", new Object[] { attribute, type, key, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Map<String, String> discriminators = getMatrixParameters(ui, persistenceUnit);
        Object entity = app.find(discriminators, type, id, getQueryParameters(ui));
        Object result = app.removeAttribute(getMatrixParameters(ui, persistenceUnit), type, id, attribute, listItemId, entity, partner);

        if (result == null) {
            JPARSLogger.fine("jpars_could_not_update_attribute", new Object[] { attribute, type, key, persistenceUnit });
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        } else {
            return Response.ok(new StreamingOutputMarshaller(app, result, hh.getAcceptableMediaTypes())).build();
        }
    }

    protected Response delete(String version, String persistenceUnit, String type, String key, UriInfo ui, HttpHeaders hh, URI baseURI) {
        PersistenceContext app = getPersistenceContext(persistenceUnit, baseURI, version, null);
        if (app == null || app.getClass(type) == null) {
            if (app == null) {
                JPARSLogger.fine("jpars_could_not_find_persistence_context", new Object[] { persistenceUnit });
            } else {
                JPARSLogger.fine("jpars_could_not_find_class_in_persistence_unit", new Object[] { type, persistenceUnit });
            }
            return Response.status(Status.NOT_FOUND).type(StreamingOutputMarshaller.getResponseMediaType(hh)).build();
        }

        Map<String, String> discriminators = getMatrixParameters(ui, persistenceUnit);
        Object id = IdHelper.buildId(app, type, key);
        app.delete(discriminators, type, id);
        return Response.ok().build();
    }

    @SuppressWarnings("rawtypes")
    private Boolean collectionContainsDomainObjects(Object object) {
        if (!(object instanceof Collection)) {
            return null;
        }
        Collection collection = (Collection) object;
        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
            Object collectionItem = iterator.next();
            if (PersistenceWeavedRest.class.isAssignableFrom(collectionItem.getClass())) {
                return true;
            }
        }
        return false;
    }

    @SuppressWarnings({ "rawtypes", "unchecked" })
    private SimpleHomogeneousList populateSimpleHomogeneousList(Collection collection, String attributeName) {
        SimpleHomogeneousList simpleList = new SimpleHomogeneousList();
        List<JAXBElement> items = new ArrayList<JAXBElement>();

        for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
            Object collectionItem = iterator.next();
            if (!(PersistenceWeavedRest.class.isAssignableFrom(collectionItem.getClass()))) {
                JAXBElement jaxbElement = new JAXBElement(new QName(attributeName), collectionItem.getClass(), collectionItem);
                items.add(jaxbElement);
            }
        }
        simpleList.setItems(items);
        return simpleList;
    }
}
TOP

Related Classes of org.eclipse.persistence.jpa.rs.resources.common.AbstractEntityResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.