/*******************************************************************************
* Copyright (c) 2011, 2014 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.
*
* Contributors:
* Dmitry Kornilov - pagination related changes
******************************************************************************/
package org.eclipse.persistence.jpa.rs.resources.common;
import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
import org.eclipse.persistence.internal.queries.ReportItem;
import org.eclipse.persistence.jpa.rs.PersistenceContext;
import org.eclipse.persistence.jpa.rs.QueryParameters;
import org.eclipse.persistence.jpa.rs.ReservedWords;
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.core.selflinks.SelfLinksResponseBuilder;
import org.eclipse.persistence.jpa.rs.features.paging.PageableQueryValidator;
import org.eclipse.persistence.jpa.rs.features.paging.PagingResponseBuilder;
import org.eclipse.persistence.jpa.rs.util.JPARSLogger;
import org.eclipse.persistence.jpa.rs.util.StreamingOutputMarshaller;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.ReportQuery;
import javax.persistence.Query;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import java.util.List;
import java.util.Map;
/**
* Base class for query resource.
*
* @author gonural
*/
public abstract class AbstractQueryResource extends AbstractResource {
private static final String CLASS_NAME = AbstractQueryResource.class.getName();
/**
* Named query update internal.
*
* @param version the version
* @param persistenceUnit the persistence unit
* @param queryName the name
* @param headers the http headers
* @param uriInfo the uri info
* @return the response
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
protected Response namedQueryUpdateInternal(String version, String persistenceUnit, String queryName, HttpHeaders headers, UriInfo uriInfo) {
JPARSLogger.entering(CLASS_NAME, "namedQueryUpdateInternal", new Object[] { "POST", version, persistenceUnit, queryName, uriInfo.getRequestUri().toASCIIString() });
try {
PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);
int result = context.queryExecuteUpdate(getMatrixParameters(uriInfo, persistenceUnit), queryName, getMatrixParameters(uriInfo, queryName), getQueryParameters(uriInfo));
JAXBElement jaxbElement = new JAXBElement(new QName(ReservedWords.NO_ROUTE_JAXB_ELEMENT_LABEL), Integer.class, result);
return Response.ok(new StreamingOutputMarshaller(context, jaxbElement, headers.getAcceptableMediaTypes())).build();
} catch (Exception ex) {
throw JPARSException.exceptionOccurred(ex);
}
}
/**
* Executes given named query.
*
* @param version the version
* @param persistenceUnit the persistence unit
* @param queryName named query to execute
* @param headers the http headers
* @param uriInfo the uri info
* @return the response
*/
protected Response namedQueryInternal(String version, String persistenceUnit, String queryName, HttpHeaders headers, UriInfo uriInfo) {
JPARSLogger.entering(CLASS_NAME, "namedQueryInternal", new Object[] { "GET", version, persistenceUnit, queryName, uriInfo.getRequestUri().toASCIIString() });
try {
final PersistenceContext context = getPersistenceContext(persistenceUnit, null, uriInfo.getBaseUri(), version, null);
final Query query = context.buildQuery(getMatrixParameters(uriInfo, persistenceUnit), queryName, getMatrixParameters(uriInfo, queryName), getQueryParameters(uriInfo));
final DatabaseQuery dbQuery = ((EJBQueryImpl<?>) query).getDatabaseQuery();
final FeatureSet featureSet = context.getSupportedFeatureSet();
final Response response;
if (featureSet.isSupported(Feature.PAGING)) {
response = processPageableQuery(context, queryName, dbQuery, query, headers, uriInfo);
} else {
response = namedQueryResponse(context, queryName, dbQuery, query, headers, uriInfo, featureSet.getResponseBuilder(Feature.NO_PAGING));
}
return response;
} catch (Exception ex) {
throw JPARSException.exceptionOccurred(ex);
}
}
private Response processPageableQuery(PersistenceContext context, String queryName, DatabaseQuery dbQuery, Query query, HttpHeaders headers, UriInfo uriInfo) {
final PageableQueryValidator validator = new PageableQueryValidator(context, queryName, uriInfo);
if (validator.isFeatureApplicable()) {
// Do pagination
query.setFirstResult(validator.getOffset());
query.setMaxResults(validator.getLimit());
return namedQueryResponse(context, queryName, dbQuery, query, headers, uriInfo, new PagingResponseBuilder());
} else {
// No pagination
return namedQueryResponse(context, queryName, dbQuery, query, headers, uriInfo, new SelfLinksResponseBuilder());
}
}
@SuppressWarnings("unchecked")
private Response namedQueryResponse(PersistenceContext context, String queryName, DatabaseQuery dbQuery, Query query, HttpHeaders headers, UriInfo uriInfo, FeatureResponseBuilder responseBuilder) {
// We need to add limit and offset to query parameters because request builder reads it from there
Map<String, Object> queryParams = getQueryParameters(uriInfo);
if (query.getMaxResults() != -1) {
queryParams.put(QueryParameters.JPARS_PAGING_LIMIT, String.valueOf(query.getMaxResults()));
queryParams.put(QueryParameters.JPARS_PAGING_OFFSET, String.valueOf(query.getFirstResult()));
}
if (dbQuery instanceof ReportQuery) {
// simple types selected : select u.name, u.age from employee
List<ReportItem> reportItems = ((ReportQuery) dbQuery).getItems();
List<Object[]> queryResults = query.getResultList();
if ((queryResults != null) && (!queryResults.isEmpty())) {
Object list = responseBuilder.buildReportQueryResponse(context, queryParams, queryResults, reportItems, uriInfo);
if (list != null) {
return Response.ok(new StreamingOutputMarshaller(context, list, headers.getAcceptableMediaTypes())).build();
} else {
// something is wrong with the descriptors
throw JPARSException.responseCouldNotBeBuiltForNamedQueryRequest(queryName, context.getName());
}
}
return Response.ok(new StreamingOutputMarshaller(context, queryResults, headers.getAcceptableMediaTypes())).build();
}
List<Object> results = query.getResultList();
if ((results != null) && (!results.isEmpty())) {
Object list = responseBuilder.buildReadAllQueryResponse(context, queryParams, results, uriInfo);
return Response.ok(new StreamingOutputMarshaller(context, list, headers.getAcceptableMediaTypes())).build();
}
return Response.ok(new StreamingOutputMarshaller(context, results, headers.getAcceptableMediaTypes())).build();
}
}