You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by tb...@apache.org on 2013/12/19 16:31:50 UTC
[39/50] [abbrv] [OLINGO-82] Renamed the project folder name to
odata2-jpa-processor
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1b479e6c/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
new file mode 100644
index 0000000..8f3487e
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/ODataJPAResponseBuilder.java
@@ -0,0 +1,629 @@
+/*******************************************************************************
+ * 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.processor.core.jpa;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+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.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.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.processor.api.jpa.ODataJPAContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAEntityParser;
+import org.apache.olingo.odata2.processor.core.jpa.access.data.JPAExpandCallBack;
+
+public final class ODataJPAResponseBuilder {
+
+ /* Response for Read Entity Set */
+ public static <T> ODataResponse build(final List<T> jpaEntities, final GetEntitySetUriInfo resultsView,
+ final String contentType, final ODataJPAContext odataJPAContext) throws ODataJPARuntimeException {
+
+ EdmEntityType edmEntityType = null;
+ ODataResponse odataResponse = null;
+ List<ArrayList<NavigationPropertySegment>> expandList = null;
+
+ try {
+ edmEntityType = resultsView.getTargetEntitySet().getEntityType();
+ List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+ Map<String, Object> edmPropertyValueMap = null;
+ JPAEntityParser jpaResultParser = new JPAEntityParser();
+ final List<SelectItem> selectedItems = resultsView.getSelect();
+ if (selectedItems != null && selectedItems.size() > 0) {
+ for (Object jpaEntity : jpaEntities) {
+ edmPropertyValueMap =
+ jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, buildSelectItemList(selectedItems, edmEntityType));
+ edmEntityList.add(edmPropertyValueMap);
+ }
+ } else {
+ for (Object jpaEntity : jpaEntities) {
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, edmEntityType);
+ edmEntityList.add(edmPropertyValueMap);
+ }
+ }
+ expandList = resultsView.getExpand();
+ if (expandList != null && expandList.size() != 0) {
+ 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 */
+ public static ODataResponse build(final Object jpaEntity, final GetEntityUriInfo resultsView,
+ final String contentType, final ODataJPAContext oDataJPAContext) 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.size() > 0) {
+ edmPropertyValueMap =
+ jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, buildSelectItemList(selectedItems, resultsView
+ .getTargetEntitySet().getEntityType()));
+ } else {
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, edmEntityType);
+ }
+
+ expandList = resultsView.getExpand();
+ if (expandList != null && expandList.size() != 0) {
+ 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 */
+ public static ODataResponse build(final long jpaEntityCount, final ODataJPAContext oDataJPAContext)
+ 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 */
+ @SuppressWarnings("unchecked")
+ public static ODataResponse build(final List<Object> createdObjectList, final PostUriInfo uriInfo,
+ final String contentType, final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException,
+ ODataNotFoundException {
+
+ if (createdObjectList == null || createdObjectList.size() == 0 || createdObjectList.get(0) == 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(createdObjectList.get(0), edmEntityType);
+
+ List<ArrayList<NavigationPropertySegment>> expandList = null;
+ if (createdObjectList.get(1) != null
+ && ((Map<EdmNavigationProperty, EdmEntitySet>) createdObjectList.get(1)).size() > 0) {
+ expandList = getExpandList((Map<EdmNavigationProperty, EdmEntitySet>) createdObjectList.get(1));
+ HashMap<String, Object> navigationMap =
+ jpaResultParser.parse2EdmNavigationValueMap(createdObjectList.get(0),
+ constructListofNavProperty(expandList));
+ edmPropertyValueMap.putAll(navigationMap);
+ }
+ EntityProviderWriteProperties feedProperties = null;
+ try {
+ feedProperties = getEntityProviderPropertiesforPost(oDataJPAContext, uriInfo, expandList);
+ } 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 */
+ public static ODataResponse build(final Object updatedObject, final PutMergePatchUriInfo putUriInfo)
+ throws ODataJPARuntimeException, ODataNotFoundException {
+ if (updatedObject == null) {
+ throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+ }
+ return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+ }
+
+ /* Response for Delete Entity */
+ public static ODataResponse build(final Object deletedObject, final DeleteUriInfo deleteUriInfo)
+ throws ODataJPARuntimeException, ODataNotFoundException {
+
+ if (deletedObject == null) {
+ throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
+ }
+ return ODataResponse.status(HttpStatusCodes.NO_CONTENT).build();
+ }
+
+ /* Response for Function Import Single Result */
+ public static ODataResponse build(final Object result, final GetFunctionImportUriInfo resultsView)
+ throws ODataJPARuntimeException {
+
+ try {
+ final EdmFunctionImport functionImport = resultsView.getFunctionImport();
+ final EdmSimpleType type = (EdmSimpleType) functionImport.getReturnType().getType();
+
+ if (result != null) {
+ ODataResponse response = null;
+
+ 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 */
+ public static ODataResponse build(final List<Object> resultList, final GetFunctionImportUriInfo resultsView,
+ final String contentType, final ODataJPAContext oDataJPAContext) throws ODataJPARuntimeException,
+ ODataNotFoundException {
+
+ ODataResponse odataResponse = null;
+
+ if (resultList != null && !resultList.isEmpty()) {
+ JPAEntityParser jpaResultParser = new JPAEntityParser();
+ EdmType edmType = null;
+ EdmFunctionImport functionImport = null;
+ Map<String, Object> edmPropertyValueMap = null;
+ List<Map<String, Object>> edmEntityList = null;
+ Object result = null;
+ try {
+ EntityProviderWriteProperties feedProperties = null;
+
+ feedProperties =
+ EntityProviderWriteProperties.serviceRoot(oDataJPAContext.getODataContext().getPathInfo().getServiceRoot())
+ .build();
+
+ functionImport = resultsView.getFunctionImport();
+ edmType = functionImport.getReturnType().getType();
+
+ if (edmType.getKind().equals(EdmTypeKind.ENTITY) || edmType.getKind().equals(EdmTypeKind.COMPLEX)) {
+ if (functionImport.getReturnType().getMultiplicity().equals(EdmMultiplicity.MANY)) {
+ edmEntityList = new ArrayList<Map<String, Object>>();
+ for (Object jpaEntity : resultList) {
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(jpaEntity, (EdmStructuralType) edmType);
+ edmEntityList.add(edmPropertyValueMap);
+ }
+ result = edmEntityList;
+ } else {
+
+ Object resultObject = resultList.get(0);
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(resultObject, (EdmStructuralType) edmType);
+
+ result = edmPropertyValueMap;
+ }
+
+ } else if (edmType.getKind().equals(EdmTypeKind.SIMPLE)) {
+ result = resultList.get(0);
+ }
+
+ 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 */
+ public static ODataResponse build(final Object jpaEntity, final GetEntityLinkUriInfo resultsView,
+ final String contentType, final ODataJPAContext oDataJPAContext) 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 */
+ public static <T> ODataResponse build(final List<T> jpaEntities, final GetEntitySetLinksUriInfo resultsView,
+ final String contentType, final ODataJPAContext oDataJPAContext) 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 GetEntitySetUriInfo resultsView, final List<Map<String, Object>> edmEntityList)
+ throws ODataJPARuntimeException {
+ ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+
+ Integer count = null;
+ if (resultsView.getInlineCount() != null) {
+ if ((resultsView.getSkip() != null || resultsView.getTop() != null)) {
+ // when $skip and/or $top is present with $inlinecount
+ count = getInlineCountForNonFilterQueryEntitySet(edmEntityList, resultsView);
+ } else {
+ // In all other cases
+ count = resultsView.getInlineCount() == InlineCount.ALLPAGES ? edmEntityList.size() : null;
+ }
+ }
+
+ try {
+ entityFeedPropertiesBuilder =
+ EntityProviderWriteProperties.serviceRoot(odataJPAContext.getODataContext().getPathInfo().getServiceRoot());
+ entityFeedPropertiesBuilder.inlineCount(count);
+ entityFeedPropertiesBuilder.inlineCountType(resultsView.getInlineCount());
+ ExpandSelectTreeNode expandSelectTree =
+ UriParser.createExpandSelectTree(resultsView.getSelect(), resultsView.getExpand());
+ entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(odataJPAContext.getODataContext()
+ .getPathInfo().getServiceRoot(), expandSelectTree, resultsView.getExpand()));
+ entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
+
+ } catch (ODataException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+
+ return entityFeedPropertiesBuilder.build();
+ }
+
+ /*
+ * 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) {
+ 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.retainAll(edmEntityList.subList(0, resultsView.getTop()));
+ }
+ }
+ }// 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, final PostUriInfo resultsView,
+ final List<ArrayList<NavigationPropertySegment>> expandList) throws ODataJPARuntimeException {
+ ODataEntityProviderPropertiesBuilder entityFeedPropertiesBuilder = null;
+ ExpandSelectTreeNode expandSelectTree = null;
+ try {
+ entityFeedPropertiesBuilder =
+ EntityProviderWriteProperties.serviceRoot(odataJPAContext.getODataContext().getPathInfo().getServiceRoot());
+ expandSelectTree = UriParser.createExpandSelectTree(null, expandList);
+ entityFeedPropertiesBuilder.expandSelectTree(expandSelectTree);
+ entityFeedPropertiesBuilder.callbacks(JPAExpandCallBack.getCallbacks(odataJPAContext.getODataContext()
+ .getPathInfo().getServiceRoot(), expandSelectTree, expandList));
+ } catch (ODataException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+
+ return entityFeedPropertiesBuilder.build();
+ }
+
+ private static List<ArrayList<NavigationPropertySegment>> getExpandList(
+ final Map<EdmNavigationProperty, EdmEntitySet> navPropEntitySetMap) {
+ List<ArrayList<NavigationPropertySegment>> expandList = new ArrayList<ArrayList<NavigationPropertySegment>>();
+ ArrayList<NavigationPropertySegment> navigationPropertySegmentList = new ArrayList<NavigationPropertySegment>();
+ for (Map.Entry<EdmNavigationProperty, EdmEntitySet> entry : navPropEntitySetMap.entrySet()) {
+ final EdmNavigationProperty edmNavigationProperty = entry.getKey();
+ final EdmEntitySet edmEntitySet = entry.getValue();
+ NavigationPropertySegment navigationPropertySegment = new NavigationPropertySegment() {
+
+ @Override
+ public EdmEntitySet getTargetEntitySet() {
+ return edmEntitySet;
+ }
+
+ @Override
+ public EdmNavigationProperty getNavigationProperty() {
+ return edmNavigationProperty;
+ }
+ };
+ navigationPropertySegmentList.add(navigationPropertySegment);
+ }
+ expandList.add(navigationPropertySegmentList);
+ return expandList;
+ }
+
+ 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) {
+ selectPropertyList.add(selectItem.getProperty());
+ }
+ for (EdmProperty keyProperty : entity.getKeyProperties()) {
+ flag = true;
+ for (SelectItem selectedItem : selectItems) {
+ if (selectedItem.getProperty().equals(keyProperty)) {
+ flag = false;
+ break;
+ }
+ }
+ if (flag == true) {
+ 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;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1b479e6c/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntity.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntity.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntity.java
new file mode 100644
index 0000000..7c2ad29
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntity.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+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.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.api.edm.EdmTyped;
+import org.apache.olingo.odata2.api.ep.entry.ODataEntry;
+import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public class JPAEntity {
+
+ private Object jpaEntity = null;
+ private EdmEntityType oDataEntityType = null;
+ private EdmEntitySet oDataEntitySet = null;
+ private Class<?> jpaType = null;
+ private HashMap<String, Method> accessModifiersWrite = null;
+ private JPAEntityParser jpaEntityParser = null;
+ public HashMap<EdmNavigationProperty, EdmEntitySet> inlinedEntities = null;
+
+ public JPAEntity(final EdmEntityType oDataEntityType, final EdmEntitySet oDataEntitySet) {
+ this.oDataEntityType = oDataEntityType;
+ this.oDataEntitySet = oDataEntitySet;
+ try {
+ JPAEdmMapping mapping = (JPAEdmMapping) oDataEntityType.getMapping();
+ jpaType = mapping.getJPAType();
+ } catch (EdmException e) {
+ return;
+ }
+ jpaEntityParser = new JPAEntityParser();
+ }
+
+ public void setAccessModifersWrite(final HashMap<String, Method> accessModifiersWrite) {
+ this.accessModifiersWrite = accessModifiersWrite;
+ }
+
+ public Object getJPAEntity() {
+ return jpaEntity;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void write(final Map<String, Object> oDataEntryProperties, final boolean isCreate)
+ throws ODataJPARuntimeException {
+ try {
+
+ EdmStructuralType structuralType = null;
+ final List<String> keyNames = oDataEntityType.getKeyPropertyNames();
+
+ if (isCreate) {
+ jpaEntity = instantiateJPAEntity();
+ } else if (jpaEntity == null) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.RESOURCE_NOT_FOUND, null);
+ }
+
+ if (accessModifiersWrite == null) {
+ accessModifiersWrite =
+ jpaEntityParser.getAccessModifiers(jpaEntity, oDataEntityType, JPAEntityParser.ACCESS_MODIFIER_SET);
+ }
+
+ if (oDataEntityType == null || oDataEntryProperties == null) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.GENERAL, null);
+ }
+
+ final HashMap<String, String> embeddableKeys =
+ jpaEntityParser.getJPAEmbeddableKeyMap(jpaEntity.getClass().getName());
+ Set<String> propertyNames = null;
+ if (embeddableKeys != null) {
+ setEmbeddableKeyProperty(embeddableKeys, oDataEntityType.getKeyProperties(), oDataEntryProperties, jpaEntity);
+ propertyNames = new HashSet<String>();
+ propertyNames.addAll(oDataEntryProperties.keySet());
+ for (String propertyName : oDataEntityType.getKeyPropertyNames()) {
+ propertyNames.remove(propertyName);
+ }
+ } else {
+ propertyNames = oDataEntryProperties.keySet();
+ }
+
+ for (String propertyName : propertyNames) {
+ EdmTyped edmTyped = (EdmTyped) oDataEntityType.getProperty(propertyName);
+
+ Method accessModifier = null;
+
+ switch (edmTyped.getType().getKind()) {
+ case SIMPLE:
+ if (isCreate == false) {
+ if (keyNames.contains(edmTyped.getName())) {
+ continue;
+ }
+ }
+ accessModifier = accessModifiersWrite.get(propertyName);
+ setProperty(accessModifier, jpaEntity, oDataEntryProperties.get(propertyName));
+ break;
+ case COMPLEX:
+ structuralType = (EdmStructuralType) edmTyped.getType();
+ accessModifier = accessModifiersWrite.get(propertyName);
+ setComplexProperty(accessModifier, jpaEntity,
+ structuralType,
+ (HashMap<String, Object>) oDataEntryProperties.get(propertyName));
+ break;
+ case NAVIGATION:
+ case ENTITY:
+ structuralType = (EdmStructuralType) edmTyped.getType();
+ EdmNavigationProperty navProperty = (EdmNavigationProperty) edmTyped;
+ accessModifier =
+ jpaEntityParser.getAccessModifier(jpaEntity, navProperty,
+ JPAEntityParser.ACCESS_MODIFIER_SET);
+ EdmEntitySet edmRelatedEntitySet = oDataEntitySet.getRelatedEntitySet(navProperty);
+ List<ODataEntry> relatedEntries = (List<ODataEntry>) oDataEntryProperties.get(propertyName);
+ Collection<Object> relatedJPAEntites = instantiateRelatedJPAEntities(jpaEntity, navProperty);
+ JPAEntity relatedEntity = new JPAEntity((EdmEntityType) structuralType, edmRelatedEntitySet);
+ for (ODataEntry oDataEntry : relatedEntries) {
+ relatedEntity.create(oDataEntry);
+ relatedJPAEntites.add(relatedEntity.getJPAEntity());
+ }
+
+ switch (navProperty.getMultiplicity()) {
+ case MANY:
+ accessModifier.invoke(jpaEntity, relatedJPAEntites);
+ break;
+ case ONE:
+ case ZERO_TO_ONE:
+ accessModifier.invoke(jpaEntity, relatedJPAEntites.iterator().next());
+ break;
+ }
+
+ if (inlinedEntities == null) {
+ inlinedEntities = new HashMap<EdmNavigationProperty, EdmEntitySet>();
+ }
+
+ inlinedEntities.put((EdmNavigationProperty) edmTyped, edmRelatedEntitySet);
+ default:
+ continue;
+ }
+ }
+ } catch (Exception e) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.GENERAL
+ .addContent(e.getMessage()), e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Collection<Object> instantiateRelatedJPAEntities(final Object jpaEntity,
+ final EdmNavigationProperty navProperty)
+ throws InstantiationException,
+ IllegalAccessException, EdmException, ODataJPARuntimeException, IllegalArgumentException,
+ InvocationTargetException {
+ Method accessModifier =
+ jpaEntityParser.getAccessModifier(jpaEntity, navProperty, JPAEntityParser.ACCESS_MODIFIER_GET);
+ Collection<Object> relatedJPAEntities = (Collection<Object>) accessModifier.invoke(jpaEntity);
+ if (relatedJPAEntities == null) {
+ relatedJPAEntities = new ArrayList<Object>();
+ }
+ return relatedJPAEntities;
+ }
+
+ public void create(final ODataEntry oDataEntry) throws ODataJPARuntimeException {
+ if (oDataEntry == null) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.GENERAL, null);
+ }
+ Map<String, Object> oDataEntryProperties = oDataEntry.getProperties();
+ if (oDataEntry.containsInlineEntry()) {
+ normalizeInlineEntries(oDataEntryProperties);
+ }
+ write(oDataEntryProperties, true);
+ }
+
+ public void create(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
+ normalizeInlineEntries(oDataEntryProperties);
+ write(oDataEntryProperties, true);
+ }
+
+ public void update(final ODataEntry oDataEntry) throws ODataJPARuntimeException {
+ if (oDataEntry == null) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.GENERAL, null);
+ }
+ Map<String, Object> oDataEntryProperties = oDataEntry.getProperties();
+ write(oDataEntryProperties, false);
+ }
+
+ public void update(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
+ write(oDataEntryProperties, false);
+ }
+
+ public HashMap<EdmNavigationProperty, EdmEntitySet> getInlineJPAEntities() {
+ return inlinedEntities;
+ }
+
+ public void setJPAEntity(final Object jpaEntity) {
+ this.jpaEntity = jpaEntity;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void setComplexProperty(Method accessModifier, final Object jpaEntity,
+ final EdmStructuralType edmComplexType, final HashMap<String, Object> propertyValue)
+ throws EdmException, IllegalAccessException, IllegalArgumentException, InvocationTargetException,
+ InstantiationException, ODataJPARuntimeException {
+
+ JPAEdmMapping mapping = (JPAEdmMapping) edmComplexType.getMapping();
+ Object embeddableObject = mapping.getJPAType().newInstance();
+ accessModifier.invoke(jpaEntity, embeddableObject);
+
+ HashMap<String, Method> accessModifiers =
+ jpaEntityParser.getAccessModifiers(embeddableObject, edmComplexType, JPAEntityParser.ACCESS_MODIFIER_SET);
+
+ for (String edmPropertyName : edmComplexType.getPropertyNames()) {
+ EdmTyped edmTyped = (EdmTyped) edmComplexType.getProperty(edmPropertyName);
+ accessModifier = accessModifiers.get(edmPropertyName);
+ if (edmTyped.getType().getKind().toString().equals(EdmTypeKind.COMPLEX.toString())) {
+ EdmStructuralType structualType = (EdmStructuralType) edmTyped.getType();
+ setComplexProperty(accessModifier, embeddableObject, structualType, (HashMap<String, Object>) propertyValue
+ .get(edmPropertyName));
+ } else {
+ setProperty(accessModifier, embeddableObject, propertyValue.get(edmPropertyName));
+ }
+ }
+ }
+
+ protected void setProperty(final Method method, final Object entity, final Object entityPropertyValue) throws
+ IllegalAccessException, IllegalArgumentException, InvocationTargetException {
+ if (entityPropertyValue != null) {
+ Class<?> parameterType = method.getParameterTypes()[0];
+ if (parameterType.equals(char[].class)) {
+ char[] characters = ((String) entityPropertyValue).toCharArray();
+ method.invoke(entity, characters);
+ } else if (parameterType.equals(char.class)) {
+ char c = ((String) entityPropertyValue).charAt(0);
+ method.invoke(entity, c);
+ } else if (parameterType.equals(Character[].class)) {
+ Character[] characters = JPAEntityParser.toCharacterArray((String) entityPropertyValue);
+ method.invoke(entity, (Object) characters);
+ } else if (parameterType.equals(Character.class)) {
+ Character c = Character.valueOf(((String) entityPropertyValue).charAt(0));
+ method.invoke(entity, c);
+ } else {
+ method.invoke(entity, entityPropertyValue);
+ }
+ }
+ }
+
+ protected void setEmbeddableKeyProperty(final HashMap<String, String> embeddableKeys,
+ final List<EdmProperty> oDataEntryKeyProperties,
+ final Map<String, Object> oDataEntryProperties, final Object entity)
+ throws ODataJPARuntimeException, EdmException, IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException, InstantiationException {
+
+ HashMap<String, Object> embeddableObjMap = new HashMap<String, Object>();
+ List<EdmProperty> leftODataEntryKeyProperties = new ArrayList<EdmProperty>();
+ HashMap<String, String> leftEmbeddableKeys = new HashMap<String, String>();
+
+ for (EdmProperty edmProperty : oDataEntryKeyProperties) {
+ if (oDataEntryProperties.containsKey(edmProperty.getName()) == false) {
+ continue;
+ }
+
+ String edmPropertyName = edmProperty.getName();
+ String embeddableKeyNameComposite = embeddableKeys.get(edmPropertyName);
+ String embeddableKeyNameSplit[] = embeddableKeyNameComposite.split("\\.");
+ String methodPartName = null;
+ Method method = null;
+ Object embeddableObj = null;
+
+ if (embeddableObjMap.containsKey(embeddableKeyNameSplit[0]) == false) {
+ methodPartName = embeddableKeyNameSplit[0];
+ method = jpaEntityParser.getAccessModifierSet(entity, methodPartName);
+ embeddableObj = method.getParameterTypes()[0].newInstance();
+ method.invoke(entity, embeddableObj);
+ embeddableObjMap.put(embeddableKeyNameSplit[0], embeddableObj);
+ } else {
+ embeddableObj = embeddableObjMap.get(embeddableKeyNameSplit[0]);
+ }
+
+ if (embeddableKeyNameSplit.length == 2) {
+ methodPartName = embeddableKeyNameSplit[1];
+ method = jpaEntityParser.getAccessModifierSet(embeddableObj, methodPartName);
+ Object simpleObj = oDataEntryProperties.get(edmProperty.getName());
+ method.invoke(embeddableObj, simpleObj);
+ } else if (embeddableKeyNameSplit.length > 2) { // Deeply nested
+ leftODataEntryKeyProperties.add(edmProperty);
+ leftEmbeddableKeys
+ .put(edmPropertyName, embeddableKeyNameComposite.split(embeddableKeyNameSplit[0] + ".", 2)[1]);
+ setEmbeddableKeyProperty(leftEmbeddableKeys, leftODataEntryKeyProperties, oDataEntryProperties, embeddableObj);
+ }
+
+ }
+ }
+
+ protected Object instantiateJPAEntity() throws InstantiationException, IllegalAccessException {
+ if (jpaType == null) {
+ throw new InstantiationException();
+ }
+
+ return jpaType.newInstance();
+ }
+
+ private void normalizeInlineEntries(final Map<String, Object> oDataEntryProperties) throws ODataJPARuntimeException {
+ List<ODataEntry> entries = null;
+ try {
+ for (String navigationPropertyName : oDataEntityType.getNavigationPropertyNames()) {
+ Object inline = oDataEntryProperties.get(navigationPropertyName);
+ if (inline instanceof ODataFeed) {
+ entries = ((ODataFeed) inline).getEntries();
+ } else if (inline instanceof ODataEntry) {
+ entries = new ArrayList<ODataEntry>();
+ entries.add((ODataEntry) inline);
+ }
+ if (entries != null) {
+ oDataEntryProperties.put(navigationPropertyName, entries);
+ entries = null;
+ }
+ }
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException
+ .throwException(ODataJPARuntimeException.GENERAL
+ .addContent(e.getMessage()), e);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1b479e6c/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
new file mode 100644
index 0000000..756e1ca
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAEntityParser.java
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.List;
+
+import org.apache.olingo.odata2.api.edm.EdmAssociationEnd;
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmNavigationProperty;
+import org.apache.olingo.odata2.api.edm.EdmProperty;
+import org.apache.olingo.odata2.api.edm.EdmStructuralType;
+import org.apache.olingo.odata2.api.edm.EdmTypeKind;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public final class JPAEntityParser {
+
+ /*
+ * List of buffers used by the Parser
+ */
+ private static short MAX_SIZE = 10;
+ public static final String ACCESS_MODIFIER_GET = "get";
+ public static final String ACCESS_MODIFIER_SET = "set";
+
+ private HashMap<String, HashMap<String, Method>> jpaEntityAccessMap = null;
+ private HashMap<String, HashMap<String, String>> jpaEmbeddableKeyMap = null;
+
+ public JPAEntityParser() {
+ jpaEntityAccessMap = new HashMap<String, HashMap<String, Method>>(
+ MAX_SIZE);
+ jpaEmbeddableKeyMap = new HashMap<String, HashMap<String, String>>();
+ };
+
+ public HashMap<String, Method> getJPAEntityAccessMap(final String jpaEntityName) {
+ return jpaEntityAccessMap.get(jpaEntityName);
+ }
+
+ public HashMap<String, String> getJPAEmbeddableKeyMap(final String jpaEntityName) {
+ return jpaEmbeddableKeyMap.get(jpaEntityName);
+ }
+
+ /**
+ * The method returns a Hash Map of Properties and values for selected
+ * properties of an EdmEntity Type
+ *
+ * @param jpaEntity
+ * @param selectedItems
+ * @return a Hash Map of Properties and values for given selected properties
+ * of an EdmEntity Type
+ * @throws ODataJPARuntimeException
+ */
+
+ public final HashMap<String, Object> parse2EdmPropertyValueMap(
+ final Object jpaEntity, final List<EdmProperty> selectPropertyList)
+ throws ODataJPARuntimeException {
+ HashMap<String, Object> edmEntity = new HashMap<String, Object>();
+ String methodName = null;
+ Method method = null;
+ for (int i = 0; i < selectPropertyList.size(); i++) {
+ String key = null;
+ Object propertyValue = null;
+ EdmProperty property = null;
+ property = selectPropertyList.get(i);
+
+ try {
+ methodName = getAccessModifierName(property.getName(),
+ property.getMapping(), ACCESS_MODIFIER_GET);
+ String[] nameParts = methodName.split("\\.");
+ if (nameParts.length > 1) {
+ Object propertyVal = new Object();
+ propertyVal = jpaEntity;
+ for (String namePart : nameParts) {
+ method = propertyVal.getClass().getMethod(
+ namePart, (Class<?>[]) null);
+ method.setAccessible(true);
+ propertyVal = getProperty(method, propertyVal);
+ }
+ edmEntity.put(property.getName(), propertyVal);
+ } else {
+ method = jpaEntity.getClass().getMethod(methodName,
+ (Class<?>[]) null);
+ method.setAccessible(true);
+ propertyValue = getProperty(method, jpaEntity);
+ key = property.getName();
+ if (property.getType().getKind()
+ .equals(EdmTypeKind.COMPLEX)) {
+ try {
+ propertyValue = parse2EdmPropertyValueMap(
+ propertyValue,
+ (EdmStructuralType) property.getType());
+ } catch (ODataJPARuntimeException e) {
+ throw e;
+ }
+ }
+ edmEntity.put(key, propertyValue);
+ }
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (IllegalArgumentException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+ }
+
+ return edmEntity;
+ }
+
+ /**
+ * The method returns a Hash Map of Properties and values for an EdmEntity
+ * Type The method uses reflection on object jpaEntity to get the list of
+ * accessModifier method. Then uses the accessModifier method to extract the value from
+ * JPAEntity.
+ *
+ * @param jpaEntity
+ * @param structuralType
+ * @return a Hash Map of Properties and values for given EdmEntity Type
+ * @throws ODataJPARuntimeException
+ */
+ public final HashMap<String, Object> parse2EdmPropertyValueMap(
+ final Object jpaEntity, final EdmStructuralType structuralType)
+ throws ODataJPARuntimeException {
+
+ if (jpaEntity == null || structuralType == null) {
+ return null;
+ }
+
+ String jpaEntityAccessKey = jpaEntity.getClass().getName();
+
+ if (!jpaEntityAccessMap.containsKey(jpaEntityAccessKey)) {
+ jpaEntityAccessMap.put(jpaEntityAccessKey,
+ getAccessModifiers(jpaEntity, structuralType, ACCESS_MODIFIER_GET));
+ }
+
+ HashMap<String, Object> edmEntity = new HashMap<String, Object>();
+ HashMap<String, Method> getters = jpaEntityAccessMap
+ .get(jpaEntityAccessKey);
+ HashMap<String, String> embeddableKeys = jpaEmbeddableKeyMap
+ .get(jpaEntityAccessKey);
+
+ try {
+ for (String key : getters.keySet()) {
+
+ EdmProperty property = (EdmProperty) structuralType
+ .getProperty(key);
+
+ Method method = getters.get(key);
+ Object propertyValue = null;
+
+ if (method != null) {
+ getters.get(key).setAccessible(true);
+ propertyValue = getProperty(method, jpaEntity);
+ }
+ if (property.getType().getKind().equals(EdmTypeKind.COMPLEX)) {
+ propertyValue = parse2EdmPropertyValueMap(propertyValue,
+ (EdmStructuralType) property.getType());
+ }
+
+ edmEntity.put(key, propertyValue);
+
+ }
+
+ if (embeddableKeys != null) {
+ for (String key : embeddableKeys.keySet()) {
+ String name = embeddableKeys.get(key);
+ String[] nameParts = name.split("\\.");
+ Object propertyValue = jpaEntity;
+ Method method = null;
+ for (String namePart : nameParts) {
+ method = propertyValue.getClass().getMethod(
+ namePart, (Class<?>[]) null);
+ method.setAccessible(true);
+ propertyValue = getProperty(method, propertyValue);
+ }
+ edmEntity.put(key, propertyValue);
+ }
+ }
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (IllegalArgumentException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+ return edmEntity;
+ }
+
+ // This method appends the associated entities as a java list to an expanded
+ // map of a source entity
+ public final HashMap<String, Object> parse2EdmNavigationValueMap(
+ final Object jpaEntity, final List<EdmNavigationProperty> navigationPropertyList)
+ throws ODataJPARuntimeException {
+ Object result = null;
+ String methodName = null;
+ HashMap<String, Object> navigationMap = new HashMap<String, Object>();
+ if (navigationPropertyList != null
+ && navigationPropertyList.size() != 0) {
+
+ try {
+ for (EdmNavigationProperty navigationProperty : navigationPropertyList) {
+ methodName = getAccessModifierName(navigationProperty.getName(),
+ navigationProperty.getMapping(), ACCESS_MODIFIER_GET);
+ Method getterMethod = jpaEntity.getClass()
+ .getDeclaredMethod(methodName, (Class<?>[]) null);
+ getterMethod.setAccessible(true);
+ result = getProperty(getterMethod, jpaEntity);
+ navigationMap.put(navigationProperty.getName(), result);
+ }
+ } catch (IllegalArgumentException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+ }
+ return navigationMap;
+ }
+
+ public Method getAccessModifierSet(final Object jpaEntity, final String methodName) throws ODataJPARuntimeException {
+ Class<?> jpaType = jpaEntity.getClass();
+ String methodNameGet = ACCESS_MODIFIER_GET + methodName.substring(3);
+ Method method = null;
+
+ try {
+ method = jpaType.getMethod(methodNameGet, (Class<?>[]) null);
+ Class<?> parameterType = method.getReturnType();
+ method = jpaType.getMethod(methodName, new Class<?>[] { parameterType });
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+
+ return method;
+ }
+
+ public HashMap<String, Method> getAccessModifiers(final Object jpaEntity,
+ final EdmStructuralType structuralType, final String accessModifier) throws ODataJPARuntimeException {
+
+ HashMap<String, Method> accessModifierMap = new HashMap<String, Method>();
+ HashMap<String, String> embeddableKey = new HashMap<String, String>();
+ try {
+ for (String propertyName : structuralType.getPropertyNames()) {
+
+ EdmProperty property = (EdmProperty) structuralType
+ .getProperty(propertyName);
+
+ String name = getAccessModifierName(property.getName(),
+ property.getMapping(), accessModifier);
+ String[] nameParts = name.split("\\.");
+ if (nameParts.length > 1) {
+ embeddableKey.put(propertyName, name);
+ } else {
+ if (accessModifier.equals(ACCESS_MODIFIER_SET)) {
+ JPAEdmMapping jpaEdmMapping = (JPAEdmMapping) property.getMapping();
+ accessModifierMap.put(
+ propertyName,
+ jpaEntity.getClass().getMethod(name, new Class<?>[] { jpaEdmMapping.getJPAType() }));
+ } else {
+ accessModifierMap.put(
+ propertyName,
+ jpaEntity.getClass().getMethod(name,
+ (Class<?>[]) null));
+ }
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+
+ if (!embeddableKey.isEmpty()) {
+ jpaEmbeddableKeyMap.put(jpaEntity.getClass().getName(),
+ embeddableKey);
+ }
+ return accessModifierMap;
+ }
+
+ public static Object getProperty(final Method method, final Object entity) throws ODataJPARuntimeException {
+ Object propertyValue = null;
+ try {
+ Class<?> returnType = method.getReturnType();
+
+ if (returnType.equals(char[].class)) {
+ char[] ch = (char[]) method.invoke(entity);
+ if (ch != null) {
+ propertyValue = (String) String.valueOf((char[]) method.invoke(entity));
+ }
+ } else if (returnType.equals(Character[].class)) {
+ propertyValue = (String) toString((Character[]) method.invoke(entity));
+ } else if (returnType.equals(char.class)) {
+ char c = (Character) method.invoke(entity);
+ if (c != '\u0000') {
+ propertyValue = (String) String.valueOf(c);
+ }
+ } else if (returnType.equals(Character.class)) {
+ Character c = (Character) method.invoke(entity);
+ if (c != null) {
+ propertyValue = toString(new Character[] { c });
+ }
+ } else {
+ propertyValue = method.invoke(entity);
+ }
+ } catch (IllegalAccessException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (IllegalArgumentException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (InvocationTargetException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+ return propertyValue;
+ }
+
+ public static String toString(final Character[] input) {
+ if (input == null) {
+ return null;
+ }
+
+ StringBuilder builder = new StringBuilder();
+ for (Character element : input) {
+ if (element == null) {
+ continue;
+ }
+ builder.append(element.charValue());
+ }
+ return builder.toString();
+
+ }
+
+ public static Character[] toCharacterArray(final String input) {
+ if (input == null) {
+ return null;
+ }
+
+ Character[] characters = new Character[input.length()];
+ char[] chars = ((String) input).toCharArray();
+ for (int i = 0; i < input.length(); i++) {
+ characters[i] = new Character(chars[i]);
+ }
+
+ return characters;
+ }
+
+ public static String getAccessModifierName(final String propertyName, final EdmMapping mapping,
+ final String accessModifier)
+ throws ODataJPARuntimeException {
+ String name = null;
+ StringBuilder builder = new StringBuilder();
+ String[] nameParts = {};
+ if (mapping == null || mapping.getInternalName() == null) {
+ name = propertyName;
+ } else {
+ name = mapping.getInternalName();
+ }
+ if (name != null) {
+ nameParts = name.split("\\.");
+ }
+ if (nameParts.length == 1) {
+ if (name != null) {
+ char c = Character.toUpperCase(name.charAt(0));
+
+ builder.append(accessModifier).append(c).append(name.substring(1))
+ .toString();
+ }
+ } else if (nameParts.length > 1) {
+
+ for (int i = 0; i < nameParts.length; i++) {
+ name = nameParts[i];
+ char c = Character.toUpperCase(name.charAt(0));
+ if (i == 0) {
+ builder.append(accessModifier).append(c).append(name.substring(1));
+ } else {
+ builder.append(".").append(accessModifier).append(c)
+ .append(name.substring(1));
+ }
+ }
+ } else {
+ return null;
+ }
+
+ if (builder.length() > 0) {
+ return builder.toString();
+ } else {
+ return null;
+ }
+
+ }
+
+ public Method getAccessModifier(final Object jpaEntity, final EdmNavigationProperty navigationProperty,
+ final String accessModifier)
+ throws ODataJPARuntimeException {
+
+ try {
+
+ JPAEdmMapping navPropMapping = (JPAEdmMapping) navigationProperty.getMapping();
+ String name = getAccessModifierName(navigationProperty.getName(), (EdmMapping) navPropMapping, accessModifier);
+
+ Class<?>[] params = null;
+ if (accessModifier.equals(ACCESS_MODIFIER_SET)) {
+ EdmAssociationEnd end = navigationProperty.getRelationship().getEnd(navigationProperty.getToRole());
+ switch (end.getMultiplicity()) {
+ case MANY:
+ params = new Class<?>[] { navPropMapping.getJPAType() };
+ break;
+ case ONE:
+ params = new Class<?>[] { ((JPAEdmMapping) end.getEntityType().getMapping()).getJPAType() };
+ default:
+ break;
+ }
+ }
+ return jpaEntity.getClass().getMethod(name,
+ params);
+
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.INNER_EXCEPTION, e);
+ }
+
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1b479e6c/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
new file mode 100644
index 0000000..78a9ea5
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAExpandCallBack.java
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+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.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.EdmNavigationProperty;
+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.OnWriteEntryContent;
+import org.apache.olingo.odata2.api.ep.callback.OnWriteFeedContent;
+import org.apache.olingo.odata2.api.ep.callback.WriteCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteEntryCallbackResult;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackContext;
+import org.apache.olingo.odata2.api.ep.callback.WriteFeedCallbackResult;
+import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
+import org.apache.olingo.odata2.api.uri.NavigationPropertySegment;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+
+public class JPAExpandCallBack implements OnWriteFeedContent, OnWriteEntryContent, ODataCallback {
+
+ private URI baseUri;
+ private List<ArrayList<NavigationPropertySegment>> expandList;
+ private EdmEntitySet nextEntitySet = null;
+
+ private JPAExpandCallBack(final URI baseUri, final List<ArrayList<NavigationPropertySegment>> expandList) {
+ super();
+ this.baseUri = baseUri;
+ this.expandList = expandList;
+ }
+
+ @Override
+ public WriteEntryCallbackResult retrieveEntryResult(final WriteEntryCallbackContext context) {
+ WriteEntryCallbackResult result = new WriteEntryCallbackResult();
+ Map<String, Object> entry = context.getEntryData();
+ Map<String, Object> edmPropertyValueMap = null;
+ List<EdmNavigationProperty> currentNavPropertyList = null;
+ Map<String, ExpandSelectTreeNode> navigationLinks = null;
+ JPAEntityParser jpaResultParser = new JPAEntityParser();
+ EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty();
+ try {
+ Object inlinedEntry = entry.get(currentNavigationProperty.getName());
+ if (nextEntitySet == null) {
+ nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
+ }
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(inlinedEntry, nextEntitySet.getEntityType());
+ result.setEntryData(edmPropertyValueMap);
+ navigationLinks = context.getCurrentExpandSelectTreeNode().getLinks();
+ if (navigationLinks.size() > 0) {
+ currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
+ EdmNavigationProperty nextNavProperty =
+ getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty());
+ if (nextNavProperty != null) {
+ currentNavPropertyList.add(nextNavProperty);
+ }
+ HashMap<String, Object> navigationMap =
+ jpaResultParser.parse2EdmNavigationValueMap(inlinedEntry, currentNavPropertyList);
+ edmPropertyValueMap.putAll(navigationMap);
+ result.setEntryData(edmPropertyValueMap);
+ }
+ result.setInlineProperties(getInlineEntityProviderProperties(context));
+ } catch (EdmException e) {
+
+ } catch (ODataJPARuntimeException e) {
+
+ }
+
+ return result;
+ }
+
+ @Override
+ public WriteFeedCallbackResult retrieveFeedResult(final WriteFeedCallbackContext context) {
+ WriteFeedCallbackResult result = new WriteFeedCallbackResult();
+ HashMap<String, Object> inlinedEntry = (HashMap<String, Object>) context.getEntryData();
+ List<Map<String, Object>> edmEntityList = new ArrayList<Map<String, Object>>();
+ Map<String, Object> edmPropertyValueMap = null;
+ JPAEntityParser jpaResultParser = new JPAEntityParser();
+ List<EdmNavigationProperty> currentNavPropertyList = null;
+ EdmNavigationProperty currentNavigationProperty = context.getNavigationProperty();
+ try {
+ @SuppressWarnings({ "unchecked" })
+ Collection<Object> listOfItems = (Collection<Object>) inlinedEntry.get(context.getNavigationProperty().getName());
+ if (nextEntitySet == null) {
+ nextEntitySet = context.getSourceEntitySet().getRelatedEntitySet(currentNavigationProperty);
+ }
+ for (Object object : listOfItems) {
+ edmPropertyValueMap = jpaResultParser.parse2EdmPropertyValueMap(object, nextEntitySet.getEntityType());
+ edmEntityList.add(edmPropertyValueMap);
+ }
+ result.setFeedData(edmEntityList);
+ if (context.getCurrentExpandSelectTreeNode().getLinks().size() > 0) {
+ currentNavPropertyList = new ArrayList<EdmNavigationProperty>();
+ EdmNavigationProperty nextNavProperty =
+ getNextNavigationProperty(context.getSourceEntitySet().getEntityType(), context.getNavigationProperty());
+ if (nextNavProperty != null) {
+ currentNavPropertyList.add(nextNavProperty);
+ }
+ int count = 0;
+ for (Object object : listOfItems) {
+ HashMap<String, Object> navigationMap =
+ jpaResultParser.parse2EdmNavigationValueMap(object, currentNavPropertyList);
+ edmEntityList.get(count).putAll(navigationMap);
+ count++;
+ }
+ result.setFeedData(edmEntityList);
+ }
+ result.setInlineProperties(getInlineEntityProviderProperties(context));
+ } catch (EdmException e) {
+
+ } catch (ODataJPARuntimeException e) {
+
+ }
+ return result;
+ }
+
+ private EdmNavigationProperty getNextNavigationProperty(final EdmEntityType sourceEntityType,
+ final EdmNavigationProperty navigationProperty) throws EdmException {
+ for (ArrayList<NavigationPropertySegment> navPropSegments : expandList) {
+ int size = navPropSegments.size();
+ for (int i = 0; i < size; i++) {
+ EdmNavigationProperty navProperty = navPropSegments.get(i).getNavigationProperty();
+ if (navProperty.getFromRole().equalsIgnoreCase(sourceEntityType.getName())
+ && navProperty.getName().equals(navigationProperty.getName())) {
+ if (i < size - 1) {
+ return navPropSegments.get(i + 1).getNavigationProperty();
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ public static <T> Map<String, ODataCallback> getCallbacks(final URI baseUri,
+ final ExpandSelectTreeNode expandSelectTreeNode, final List<ArrayList<NavigationPropertySegment>> expandList)
+ throws EdmException {
+ Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>();
+
+ for (String navigationPropertyName : expandSelectTreeNode.getLinks().keySet()) {
+ callbacks.put(navigationPropertyName, new JPAExpandCallBack(baseUri, expandList));
+ }
+
+ return callbacks;
+
+ }
+
+ private EntityProviderWriteProperties getInlineEntityProviderProperties(final WriteCallbackContext context)
+ throws EdmException {
+ ODataEntityProviderPropertiesBuilder propertiesBuilder = EntityProviderWriteProperties.serviceRoot(baseUri);
+ propertiesBuilder.callbacks(getCallbacks(baseUri, context.getCurrentExpandSelectTreeNode(), expandList));
+ propertiesBuilder.expandSelectTree(context.getCurrentExpandSelectTreeNode());
+ return propertiesBuilder.build();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/1b479e6c/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
----------------------------------------------------------------------
diff --git a/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
new file mode 100644
index 0000000..8f79c92
--- /dev/null
+++ b/odata2-jpa-processor/jpa-core/src/main/java/org/apache/olingo/odata2/processor/core/jpa/access/data/JPAFunctionContext.java
@@ -0,0 +1,170 @@
+/*******************************************************************************
+ * 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.processor.core.jpa.access.data;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.olingo.odata2.api.edm.EdmException;
+import org.apache.olingo.odata2.api.edm.EdmFacets;
+import org.apache.olingo.odata2.api.edm.EdmFunctionImport;
+import org.apache.olingo.odata2.api.edm.EdmLiteral;
+import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
+import org.apache.olingo.odata2.api.edm.EdmMapping;
+import org.apache.olingo.odata2.api.edm.EdmParameter;
+import org.apache.olingo.odata2.api.edm.EdmSimpleType;
+import org.apache.olingo.odata2.api.edm.EdmSimpleTypeException;
+import org.apache.olingo.odata2.api.uri.info.GetFunctionImportUriInfo;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAFunction;
+import org.apache.olingo.odata2.processor.api.jpa.access.JPAMethodContext;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPAModelException;
+import org.apache.olingo.odata2.processor.api.jpa.exception.ODataJPARuntimeException;
+import org.apache.olingo.odata2.processor.api.jpa.model.JPAEdmMapping;
+
+public class JPAFunctionContext extends JPAMethodContext {
+
+ public class JPAFunctionContextBuilder extends JPAMethodContextBuilder {
+
+ protected GetFunctionImportUriInfo functiontView;
+ private EdmFunctionImport functionImport;
+ private EdmMapping mapping;
+
+ @Override
+ public JPAMethodContext build() throws ODataJPAModelException, ODataJPARuntimeException {
+ if (functiontView != null) {
+
+ functionImport = functiontView.getFunctionImport();
+ try {
+ mapping = functionImport.getMapping();
+
+ List<JPAFunction> jpaFunctionList = new ArrayList<JPAFunction>();
+ jpaFunctionList.add(generateJPAFunction());
+ setJpaFunction(jpaFunctionList);
+ setEnclosingObject(generateEnclosingObject());
+ } catch (EdmException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (InstantiationException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (IllegalAccessException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (IllegalArgumentException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (InvocationTargetException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (NoSuchMethodException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ } catch (SecurityException e) {
+ throw ODataJPARuntimeException.throwException(ODataJPARuntimeException.GENERAL.addContent(e.getMessage()), e);
+ }
+ }
+
+ return JPAFunctionContext.this;
+ }
+
+ private JPAFunction generateJPAFunction() throws EdmException, NoSuchMethodException, SecurityException,
+ ODataJPAModelException, ODataJPARuntimeException {
+
+ Class<?>[] parameterTypes = getParameterTypes();
+ Method method = getMethod(parameterTypes);
+ Type returnType = getReturnType();
+ Object[] args = getAruguments();
+
+ JPAFunction jpafunction = new JPAFunction(method, parameterTypes, returnType, args);
+
+ return jpafunction;
+ }
+
+ private Object[] getAruguments() throws EdmException {
+ Map<String, EdmLiteral> edmArguements = functiontView.getFunctionImportParameters();
+
+ if (edmArguements == null) {
+ return null;
+ } else {
+ Object[] args = new Object[edmArguements.size()];
+ int i = 0;
+ for (String paramName : functionImport.getParameterNames()) {
+ EdmLiteral literal = edmArguements.get(paramName);
+ EdmParameter parameter = functionImport.getParameter(paramName);
+ JPAEdmMapping mapping = (JPAEdmMapping) parameter.getMapping();
+ args[i] = convertArguement(literal, parameter.getFacets(), mapping.getJPAType());
+ i++;
+ }
+ return args;
+ }
+
+ }
+
+ private Object convertArguement(final EdmLiteral edmLiteral, final EdmFacets facets, final Class<?> targetType)
+ throws EdmSimpleTypeException {
+ EdmSimpleType edmType = edmLiteral.getType();
+ Object value = edmType.valueOfString(edmLiteral.getLiteral(), EdmLiteralKind.DEFAULT, facets, targetType);
+
+ return value;
+ }
+
+ private Class<?>[] getParameterTypes() throws EdmException {
+
+ Class<?>[] parameterTypes = new Class<?>[functionImport.getParameterNames().size()];
+ int i = 0;
+ for (String parameterName : functionImport.getParameterNames()) {
+ EdmParameter parameter = functionImport.getParameter(parameterName);
+ parameterTypes[i] = ((JPAEdmMapping) parameter.getMapping()).getJPAType();
+ i++;
+ }
+
+ return parameterTypes;
+ }
+
+ private Method getMethod(final Class<?>[] parameterTypes) throws NoSuchMethodException, SecurityException {
+
+ Class<?> type = ((JPAEdmMapping) mapping).getJPAType();
+ Method method;
+ method = type.getMethod(mapping.getInternalName(), parameterTypes);
+
+ return method;
+ }
+
+ private Type getReturnType() throws ODataJPAModelException, ODataJPARuntimeException, EdmException {
+ return null;
+ }
+
+ private Object generateEnclosingObject() throws InstantiationException, IllegalAccessException,
+ IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
+
+ Class<?> type = ((JPAEdmMapping) mapping).getJPAType();
+ Object[] params = null;
+
+ return type.getConstructor((Class<?>[]) params).newInstance(params);
+
+ }
+
+ @Override
+ protected void setResultsView(final Object resultsView) {
+ if (resultsView instanceof GetFunctionImportUriInfo) {
+ functiontView = (GetFunctionImportUriInfo) resultsView;
+ }
+
+ }
+
+ }
+}