blob: 80cea7dfb71c8c7d80413ab4c1176a52006fd9ca [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
******************************************************************************/
package org.apache.olingo.odata2.jpa.processor.core;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.olingo.odata2.api.ODataCallback;
import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
import org.apache.olingo.odata2.api.commons.InlineCount;
import org.apache.olingo.odata2.api.edm.EdmEntitySet;
import org.apache.olingo.odata2.api.edm.EdmEntityType;
import org.apache.olingo.odata2.api.edm.EdmException;
import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
import org.apache.olingo.odata2.api.edm.EdmMultiplicity;
import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
import org.apache.olingo.odata2.api.edm.EdmProperty;
import org.apache.olingo.odata2.api.edm.EdmSimpleType;
import org.apache.olingo.odata2.api.edm.EdmStructuralType;
import org.apache.olingo.odata2.api.edm.EdmType;
import org.apache.olingo.odata2.api.edm.EdmTypeKind;
import org.apache.olingo.odata2.api.ep.EntityProvider;
import org.apache.olingo.odata2.api.ep.EntityProviderException;
import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties.ODataEntityProviderPropertiesBuilder;
import org.apache.olingo.odata2.api.ep.callback.TombstoneCallback;
import org.apache.olingo.odata2.api.exception.ODataException;
import org.apache.olingo.odata2.api.exception.ODataHttpException;
import org.apache.olingo.odata2.api.exception.ODataNotFoundException;
import org.apache.olingo.odata2.api.processor.ODataContext;
import org.apache.olingo.odata2.api.processor.ODataResponse;
import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
import org.apache.olingo.odata2.api.uri.PathInfo;
import org.apache.olingo.odata2.api.uri.SelectItem;
import org.apache.olingo.odata2.api.uri.UriParser;
import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntitySetUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetEntityUriInfo;
import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
import org.apache.olingo.odata2.core.uri.UriInfoImpl;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAContext;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPAResponseBuilder;
import org.apache.olingo.odata2.jpa.processor.api.ODataJPATombstoneContext;
import org.apache.olingo.odata2.jpa.processor.api.access.JPAPaging;
import org.apache.olingo.odata2.jpa.processor.api.exception.ODataJPARuntimeException;
import org.apache.olingo.odata2.jpa.processor.core.access.data.JPAEntityParser;
import org.apache.olingo.odata2.jpa.processor.core.callback.JPAExpandCallBack;
import org.apache.olingo.odata2.jpa.processor.core.callback.JPATombstoneCallBack;
import org.apache.olingo.odata2.jpa.processor.core.callback.JPATombstoneCallBackFI;
public final class ODataJPAResponseBuilderDefault implements ODataJPAResponseBuilder {
private static final String COUNT = "count";
private final ODataJPAContext oDataJPAContext;
public ODataJPAResponseBuilderDefault(final ODataJPAContext context) {
oDataJPAContext = context;
}
/* Response for Read Entity Set */
@Override
public ODataResponse build(final GetEntitySetUriInfo resultsView, final List<Object> jpaEntities,
final String contentType) throws ODataJPARuntimeException {
EdmEntityType edmEntityType = null;
ODataResponse odataResponse = null;
List<ArrayList<NavigationPropertySegment>> expandList = null;
try {
edmEntityType = resultsView.getTargetEntitySet().getEntityType();
List<Map<String, Object>> edmEntityList = null;
JPAEntityParser jpaResultParser = new JPAEntityParser();
final List<SelectItem> selectedItems = resultsView.getSelect();
if (selectedItems != null && !selectedItems.isEmpty()) {
edmEntityList =
jpaResultParser.parse2EdmEntityList(jpaEntities, buildSelectItemList(selectedItems, edmEntityType));
} else {
edmEntityList = jpaResultParser.parse2EdmEntityList(jpaEntities, edmEntityType);
}
expandList = resultsView.getExpand();
if (expandList != null && !expandList.isEmpty()) {
int count = 0;
List<EdmNavigationProperty> edmNavPropertyList = constructListofNavProperty(expandList);
for (Object jpaEntity : jpaEntities) {
Map<String, Object> relationShipMap = edmEntityList.get(count);
HashMap<String, Object> navigationMap =
jpaResultParser.parse2EdmNavigationValueMap(jpaEntity, edmNavPropertyList);
relationShipMap.putAll(navigationMap);
count++;
}
}
EntityProviderWriteProperties feedProperties = null;
feedProperties = getEntityProviderProperties(oDataJPAContext, resultsView, edmEntityList);
odataResponse =
EntityProvider.writeFeed(contentType, resultsView.getTargetEntitySet(), edmEntityList, feedProperties);
odataResponse = ODataResponse.fromResponse(odataResponse).status(HttpStatusCodes.OK).build();
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return odataResponse;
}
/* Response for Read Entity */
@Override
public ODataResponse build(final GetEntityUriInfo resultsView, final Object jpaEntity,
final String contentType) throws ODataJPARuntimeException,
ODataNotFoundException {
List<ArrayList<NavigationPropertySegment>> expandList = null;
if (jpaEntity == null) {
throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
}
EdmEntityType edmEntityType = null;
ODataResponse odataResponse = null;
try {
edmEntityType = resultsView.getTargetEntitySet().getEntityType();
Map<String, Object> edmPropertyValueMap = null;
JPAEntityParser jpaResultParser = new JPAEntityParser();
final List<SelectItem> selectedItems = resultsView.getSelect();
if (selectedItems != null && !selectedItems.isEmpty()) {
edmPropertyValueMap =
jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, buildSelectItemList(selectedItems, resultsView
.getTargetEntitySet().getEntityType()));
} else {
edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, edmEntityType);
}
expandList = resultsView.getExpand();
if (expandList != null && !expandList.isEmpty()) {
HashMap<String, Object> navigationMap =
jpaResultParser.parse2EdmNavigationValueMap(jpaEntity, constructListofNavProperty(expandList));
edmPropertyValueMap.putAll(navigationMap);
}
EntityProviderWriteProperties feedProperties = null;
feedProperties = getEntityProviderProperties(oDataJPAContext, resultsView);
odataResponse =
EntityProvider.writeEntry(contentType, resultsView.getTargetEntitySet(), edmPropertyValueMap, feedProperties);
odataResponse = ODataResponse.fromResponse(odataResponse).status(HttpStatusCodes.OK).build();
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return odataResponse;
}
/* Response for $count */
@Override
public ODataResponse build(final long jpaEntityCount)
throws ODataJPARuntimeException {
ODataResponse odataResponse = null;
try {
odataResponse = EntityProvider.writeText(String.valueOf(jpaEntityCount));
odataResponse = ODataResponse.fromResponse(odataResponse).build();
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return odataResponse;
}
/* Response for Create Entity */
@Override
public ODataResponse build(final PostUriInfo uriInfo, final Object createdObject,
final String contentType) throws ODataJPARuntimeException,
ODataNotFoundException {
if (createdObject == null) {
throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
}
EdmEntityType edmEntityType = null;
ODataResponse odataResponse = null;
try {
edmEntityType = uriInfo.getTargetEntitySet().getEntityType();
Map<String, Object> edmPropertyValueMap = null;
JPAEntityParser jpaResultParser = new JPAEntityParser();
edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(createdObject, edmEntityType);
EntityProviderWriteProperties feedProperties = null;
try {
feedProperties = getEntityProviderPropertiesforPost(oDataJPAContext);
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
odataResponse =
EntityProvider.writeEntry(contentType, uriInfo.getTargetEntitySet(), edmPropertyValueMap, feedProperties);
odataResponse = ODataResponse.fromResponse(odataResponse).status(HttpStatusCodes.CREATED).build();
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return odataResponse;
}
/* Response for Update Entity */
@Override
public ODataResponse build(final PutMergePatchUriInfo putUriInfo, final Object updatedObject)
throws ODataJPARuntimeException, ODataNotFoundException {
if (updatedObject == null) {
throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
}
return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
}
/* Response for Delete Entity */
@Override
public ODataResponse build(final DeleteUriInfo deleteUriInfo, final Object deletedObject)
throws ODataJPARuntimeException, ODataNotFoundException {
if (deletedObject == null) {
throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
}
return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
}
/* Response for Function Import Single Result */
@Override
public ODataResponse build(final GetFunctionImportUriInfo resultsView, final Object result)
throws ODataJPARuntimeException {
try {
final EdmFunctionImport functionImport = resultsView.getFunctionImport();
final EdmSimpleType type = (EdmSimpleType) functionImport.getReturnType().getType();
if (result != null) {
ODataResponse response = null;
if (type.getDefaultType().equals(byte[].class)) {
response = EntityProvider.writeBinary("application/octet-stream", (byte[]) result);
} else {
final String value = type.valueToString(result, EdmLiteralKind.DEFAULT, null);
response = EntityProvider.writeText(value);
}
return ODataResponse.fromResponse(response).build();
} else {
throw new ODataNotFoundException(ODataHttpException.COMMON);
}
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
}
/* Response for Function Import Multiple Result */
@Override
public ODataResponse build(final GetFunctionImportUriInfo resultsView, final List<Object> resultList,
final String contentType) throws ODataJPARuntimeException,
ODataNotFoundException {
ODataResponse odataResponse = null;
if (resultList != null) {
JPAEntityParser jpaResultParser = new JPAEntityParser();
EdmType edmType = null;
EdmFunctionImport functionImport = null;
List<Map<String, Object>> edmEntityList = null;
Object result = null;
try {
functionImport = resultsView.getFunctionImport();
edmType = functionImport.getReturnType().getType();
final List<SelectItem> selectedItems = resultsView.getSelect();
List<ArrayList<NavigationPropertySegment>> expandList = null;
EntityProviderWriteProperties feedProperties = null;
if (edmType.getKind().equals(EdmTypeKind.ENTITY) || edmType.getKind().equals(EdmTypeKind.COMPLEX)) {
if (selectedItems != null && !selectedItems.isEmpty()) {
edmEntityList =
jpaResultParser.parse2EdmEntityList(resultList,
buildSelectItemList(selectedItems, (EdmEntityType) edmType));
} else {
edmEntityList = jpaResultParser.parse2EdmEntityList(resultList, (EdmEntityType) edmType);
}
expandList = resultsView.getExpand();
if (expandList != null && !expandList.isEmpty()) {
int count = 0;
List<EdmNavigationProperty> edmNavPropertyList = constructListofNavProperty(expandList);
for (Object jpaEntity : resultList) {
Map<String, Object> relationShipMap = edmEntityList.get(count);
HashMap<String, Object> navigationMap =
jpaResultParser.parse2EdmNavigationValueMap(jpaEntity, edmNavPropertyList);
relationShipMap.putAll(navigationMap);
count++;
}
}
if (functionImport.getReturnType().getMultiplicity().equals(EdmMultiplicity.MANY)) {
result = edmEntityList;
} else {
result = edmEntityList.get(0);
}
feedProperties =
getEntityProviderProperties(oDataJPAContext, resultsView, edmEntityList);
} else if (edmType.getKind().equals(EdmTypeKind.SIMPLE)) {
result = resultList.get(0);
feedProperties =
EntityProviderWriteProperties.serviceRoot(
oDataJPAContext.getODataContext().getPathInfo().getServiceRoot())
.build();
}
odataResponse =
EntityProvider.writeFunctionImport(contentType, resultsView.getFunctionImport(), result, feedProperties);
odataResponse = ODataResponse.fromResponse(odataResponse).status(HttpStatusCodes.OK).build();
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (EntityProviderException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
} else {
throw new ODataNotFoundException(ODataHttpException.COMMON);
}
return odataResponse;
}
/* Response for Read Entity Link */
@Override
public ODataResponse build(final GetEntityLinkUriInfo resultsView, final Object jpaEntity,
final String contentType) throws ODataNotFoundException,
ODataJPARuntimeException {
if (jpaEntity == null) {
throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
}
EdmEntityType edmEntityType = null;
ODataResponse odataResponse = null;
try {
EdmEntitySet entitySet = resultsView.getTargetEntitySet();
edmEntityType = entitySet.getEntityType();
Map<String, Object> edmPropertyValueMap = null;
JPAEntityParser jpaResultParser = new JPAEntityParser();
edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, edmEntityType.getKeyProperties());
EntityProviderWriteProperties entryProperties =
EntityProviderWriteProperties.serviceRoot(oDataJPAContext.getODataContext().getPathInfo().getServiceRoot())
.build();
ODataResponse response = EntityProvider.writeLink(contentType, entitySet, edmPropertyValueMap, entryProperties);
odataResponse = ODataResponse.fromResponse(response).build();
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return odataResponse;
}
/* Response for Read Entity Links */
@Override
public ODataResponse build(final GetEntitySetLinksUriInfo resultsView, final List<Object> jpaEntities,
final String contentType) throws ODataJPARuntimeException {
EdmEntityType edmEntityType = null;
ODataResponse odataResponse = null;
try {
EdmEntitySet entitySet = resultsView.getTargetEntitySet();
edmEntityType = entitySet.getEntityType();
List<EdmProperty> keyProperties = edmEntityType.getKeyProperties();
List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
Map<String, Object> edmPropertyValueMap = null;
JPAEntityParser jpaResultParser = new JPAEntityParser();
for (Object jpaEntity : jpaEntities) {
edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, keyProperties);
edmEntityList.add(edmPropertyValueMap);
}
Integer count = null;
if (resultsView.getInlineCount() != null) {
if ((resultsView.getSkip() != null || resultsView.getTop() != null)) {
// when $skip and/or $top is present with $inlinecount
count = getInlineCountForNonFilterQueryLinks(edmEntityList, resultsView);
} else {
// In all other cases
count = resultsView.getInlineCount() == InlineCount.ALLPAGES ? edmEntityList.size() : null;
}
}
ODataContext context = oDataJPAContext.getODataContext();
EntityProviderWriteProperties entryProperties =
EntityProviderWriteProperties.serviceRoot(context.getPathInfo().getServiceRoot()).inlineCountType(
resultsView.getInlineCount()).inlineCount(count).build();
odataResponse = EntityProvider.writeLinks(contentType, entitySet, edmEntityList, entryProperties);
odataResponse = ODataResponse.fromResponse(odataResponse).build();
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return odataResponse;
}
/*
* This method handles $inlinecount request. It also modifies the list of results in case of
* $inlinecount and $top/$skip combinations. Specific to LinksUriInfo.
*
* @param edmEntityList
*
* @param resultsView
*
* @return
*/
private static Integer getInlineCountForNonFilterQueryLinks(final List<Map<String, Object>> edmEntityList,
final GetEntitySetLinksUriInfo resultsView) {
// when $skip and/or $top is present with $inlinecount, first get the total count
Integer count = null;
if (resultsView.getInlineCount() == InlineCount.ALLPAGES) {
if (resultsView.getSkip() != null || resultsView.getTop() != null) {
count = edmEntityList.size();
// Now update the list
if (resultsView.getSkip() != null) {
// Index checks to avoid IndexOutOfBoundsException
if (resultsView.getSkip() > edmEntityList.size()) {
edmEntityList.clear();
return count;
}
edmEntityList.subList(0, resultsView.getSkip()).clear();
}
if (resultsView.getTop() != null && resultsView.getTop() >= 0 && resultsView.getTop() < edmEntityList.size()) {
edmEntityList.subList(0, resultsView.getTop());
}
}
}// Inlinecount of None is handled by default - null
return count;
}
/*
* Method to build the entity provider Property.Callbacks for $expand would
* be registered here
*/
private static EntityProviderWriteProperties getEntityProviderProperties(final ODataJPAContext odataJPAContext,
final GetFunctionImportUriInfo resultsView, final List<Map<String, Object>> edmEntityList)
throws ODataJPARuntimeException {
ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
ODataContext context = odataJPAContext.getODataContext();
Integer count = null;
if (resultsView.getInlineCount() != null) {
count = getInlineCountForNonFilterQueryEntitySet(edmEntityList, resultsView);
}
try {
PathInfo pathInfo = context.getPathInfo();
URI serviceRoot = pathInfo.getServiceRoot();
entityFeedPropertiesBuilder =
EntityProviderWriteProperties.serviceRoot(pathInfo.getServiceRoot());
JPAPaging paging = odataJPAContext.getPaging();
if (odataJPAContext.getPageSize() > 0 && paging != null && paging.getNextPage() > 0) {
String nextLink =
serviceRoot.relativize(pathInfo.getRequestUri()).toString();
nextLink = percentEncodeNextLink(nextLink);
nextLink += (nextLink != null ? nextLink.contains("?") ? "&" : "?" : "?")
+ "$skiptoken=" + odataJPAContext.getPaging().getNextPage();
entityFeedPropertiesBuilder.nextLink(nextLink);
}
entityFeedPropertiesBuilder.inlineCount(count);
entityFeedPropertiesBuilder.inlineCountType(resultsView.getInlineCount());
ExpandSelectTreeNode expandSelectTree =
UriParser.createExpandSelectTree(resultsView.getSelect(), resultsView.getExpand());
Map<String, ODataCallback> expandCallBack =
JPAExpandCallBack.getCallbacks(serviceRoot, expandSelectTree, resultsView.getExpand());
Map<String, ODataCallback> callBackMap = new HashMap<String, ODataCallback>();
callBackMap.putAll(expandCallBack);
String deltaToken = ODataJPATombstoneContext.getDeltaToken();
if (deltaToken != null) {
callBackMap.put(TombstoneCallback.CALLBACK_KEY_TOMBSTONE, new JPATombstoneCallBackFI(serviceRoot.toString(),
resultsView, deltaToken));
}
entityFeedPropertiesBuilder.callbacks(callBackMap);
entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return entityFeedPropertiesBuilder.build();
}
/*
* Method to build the entity provider Property.Callbacks for $expand would
* be registered here
*/
private static EntityProviderWriteProperties getEntityProviderProperties(final ODataJPAContext odataJPAContext,
final GetEntitySetUriInfo resultsView, final List<Map<String, Object>> edmEntityList)
throws ODataJPARuntimeException {
ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
ODataContext context = odataJPAContext.getODataContext();
Integer count = null;
if (resultsView.getInlineCount() != null) {
count = getInlineCountForNonFilterQueryEntitySet(edmEntityList, resultsView);
}
try {
PathInfo pathInfo = context.getPathInfo();
URI serviceRoot = pathInfo.getServiceRoot();
entityFeedPropertiesBuilder =
EntityProviderWriteProperties.serviceRoot(pathInfo.getServiceRoot());
JPAPaging paging = odataJPAContext.getPaging();
if (odataJPAContext.getPageSize() > 0 && paging != null && paging.getNextPage() > 0) {
String nextLink =
serviceRoot.relativize(pathInfo.getRequestUri()).toString();
nextLink = percentEncodeNextLink(nextLink);
nextLink += (nextLink != null ? nextLink.contains("?") ? "&" : "?" : "?")
+ "$skiptoken=" + odataJPAContext.getPaging().getNextPage();
entityFeedPropertiesBuilder.nextLink(nextLink);
}
entityFeedPropertiesBuilder.inlineCount(count);
entityFeedPropertiesBuilder.inlineCountType(resultsView.getInlineCount());
ExpandSelectTreeNode expandSelectTree =
UriParser.createExpandSelectTree(resultsView.getSelect(), resultsView.getExpand());
Map<String, ODataCallback> expandCallBack =
JPAExpandCallBack.getCallbacks(serviceRoot, expandSelectTree, resultsView.getExpand());
Map<String, ODataCallback> callBackMap = new HashMap<String, ODataCallback>();
callBackMap.putAll(expandCallBack);
String deltaToken = ODataJPATombstoneContext.getDeltaToken();
if (deltaToken != null) {
callBackMap.put(TombstoneCallback.CALLBACK_KEY_TOMBSTONE, new JPATombstoneCallBack(serviceRoot.toString(),
resultsView, deltaToken));
}
entityFeedPropertiesBuilder.callbacks(callBackMap);
entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return entityFeedPropertiesBuilder.build();
}
private static String percentEncodeNextLink(final String link) {
if (link == null) {
return null;
}
return link.replaceAll("\\$skiptoken=.+?(?:&|$)", "")
.replaceAll("\\$skip=.+?(?:&|$)", "")
.replaceFirst("(?:\\?|&)$", ""); // Remove potentially trailing "?" or "&" left over from remove actions
}
public static boolean isNumeric(String strNum) {
return strNum.matches("-?\\d+(\\.\\d+)?");
}
/*
* This method handles $inlinecount request. It also modifies the list of results in case of
* $inlinecount and $top/$skip combinations. Specific to Entity Set.
*/
private static Integer getInlineCountForNonFilterQueryEntitySet(final List<Map<String, Object>> edmEntityList,
final GetEntitySetUriInfo resultsView) {
// when $skip and/or $top is present with $inlinecount, first get the total count
Integer count = null;
if (resultsView.getInlineCount() == InlineCount.ALLPAGES) {
count = edmEntityList.size();
if (resultsView.getCustomQueryOptions() != null) {
String countValue = resultsView.getCustomQueryOptions().get(COUNT);
if (countValue != null && isNumeric(countValue)) {
count = Integer.parseInt(countValue);
resultsView.getCustomQueryOptions().remove(COUNT);
if (resultsView.getCustomQueryOptions().size() == 0) {
((UriInfoImpl) resultsView).setCustomQueryOptions(null);
}
}
}
}// Inlinecount of None is handled by default - null
return count;
}
/*
* This method handles $inlinecount request. It also modifies the list of results in case of
* $inlinecount and $top/$skip combinations. Specific to Entity Set.
*/
private static Integer getInlineCountForNonFilterQueryEntitySet(final List<Map<String, Object>> edmEntityList,
final GetFunctionImportUriInfo resultsView) {
// when $skip and/or $top is present with $inlinecount, first get the total count
Integer count = null;
if (resultsView.getInlineCount() == InlineCount.ALLPAGES) {
count = edmEntityList.size();
if (resultsView.getCustomQueryOptions() != null) {
String countValue = resultsView.getCustomQueryOptions().get(COUNT);
if (countValue != null && isNumeric(countValue)) {
count = Integer.parseInt(countValue);
resultsView.getCustomQueryOptions().remove(COUNT);
if (resultsView.getCustomQueryOptions().size() == 0) {
((UriInfoImpl) resultsView).setCustomQueryOptions(null);
}
}
}
}// Inlinecount of None is handled by default - null
return count;
}
private static EntityProviderWriteProperties getEntityProviderProperties(final ODataJPAContext odataJPAContext,
final GetEntityUriInfo resultsView) throws ODataJPARuntimeException {
ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
ExpandSelectTreeNode expandSelectTree = null;
try {
entityFeedPropertiesBuilder =
EntityProviderWriteProperties.serviceRoot(odataJPAContext.getODataContext().getPathInfo().getServiceRoot());
expandSelectTree = UriParser.createExpandSelectTree(resultsView.getSelect(), resultsView.getExpand());
entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(odataJPAContext.getODataContext()
.getPathInfo().getServiceRoot(), expandSelectTree, resultsView.getExpand()));
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return entityFeedPropertiesBuilder.build();
}
private static EntityProviderWriteProperties getEntityProviderPropertiesforPost(
final ODataJPAContext odataJPAContext) throws ODataJPARuntimeException {
ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
try {
entityFeedPropertiesBuilder =
EntityProviderWriteProperties.serviceRoot(odataJPAContext.getODataContext().getPathInfo().getServiceRoot());
} catch (ODataException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return entityFeedPropertiesBuilder.build();
}
private static List<EdmProperty> buildSelectItemList(final List<SelectItem> selectItems, final EdmEntityType entity)
throws ODataJPARuntimeException {
boolean flag = false;
List<EdmProperty> selectPropertyList = new ArrayList<EdmProperty>();
try {
for (SelectItem selectItem : selectItems) {
if (selectItem.getNavigationPropertySegments().size() <= 0) {
if (selectItem.isStar()) {
selectPropertyList.addAll(getEdmProperties(entity));
return selectPropertyList;
} else {
selectPropertyList.add(selectItem.getProperty());
}
}
}
for (EdmProperty keyProperty : entity.getKeyProperties()) {
flag = true;
for (SelectItem selectedItem : selectItems) {
if (!selectedItem.isStar() && keyProperty.equals(selectedItem.getProperty())) {
flag = false;
break;
}
}
if (flag) {
selectPropertyList.add(keyProperty);
}
}
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
}
return selectPropertyList;
}
private static List<EdmNavigationProperty> constructListofNavProperty(
final List<ArrayList<NavigationPropertySegment>> expandList) {
List<EdmNavigationProperty> navigationPropertyList = new ArrayList<EdmNavigationProperty>();
for (ArrayList<NavigationPropertySegment> navpropSegment : expandList) {
navigationPropertyList.add(navpropSegment.get(0).getNavigationProperty());
}
return navigationPropertyList;
}
private static List<EdmProperty> getEdmProperties(final EdmStructuralType structuralType)
throws ODataJPARuntimeException {
List<EdmProperty> edmProperties = new ArrayList<EdmProperty>();
try {
for (String propertyName : structuralType.getPropertyNames()) {
edmProperties.add((EdmProperty) structuralType.getProperty(propertyName));
}
} catch (EdmException e) {
throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
}
return edmProperties;
}
}