You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2013/12/05 13:31:39 UTC
[46/52] Renamed project
http://git-wip-us.apache.org/repos/asf/incubator-olingo-odata2/blob/12ea18ae/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/ListsProcessor.java
----------------------------------------------------------------------
diff --git a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/ListsProcessor.java b/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/ListsProcessor.java
deleted file mode 100644
index 19218d7..0000000
--- a/odata2-edm-annotation/edm-annotation-core/src/main/java/org/apache/olingo/odata2/core/annotation/processor/ListsProcessor.java
+++ /dev/null
@@ -1,1630 +0,0 @@
-/*******************************************************************************
- * 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.core.annotation.processor;
-
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.olingo.odata2.api.ODataCallback;
-import org.apache.olingo.odata2.api.batch.BatchHandler;
-import org.apache.olingo.odata2.api.batch.BatchRequestPart;
-import org.apache.olingo.odata2.api.batch.BatchResponsePart;
-import org.apache.olingo.odata2.api.commons.HttpContentType;
-import org.apache.olingo.odata2.api.commons.HttpStatusCodes;
-import org.apache.olingo.odata2.api.commons.InlineCount;
-import org.apache.olingo.odata2.api.data.DataSource;
-import org.apache.olingo.odata2.api.data.DataSource.BinaryData;
-import org.apache.olingo.odata2.api.data.DataSourceProcessor;
-import org.apache.olingo.odata2.api.data.ValueAccess;
-import org.apache.olingo.odata2.api.edm.Edm;
-import org.apache.olingo.odata2.api.edm.EdmConcurrencyMode;
-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.EdmLiteral;
-import org.apache.olingo.odata2.api.edm.EdmLiteralKind;
-import org.apache.olingo.odata2.api.edm.EdmMapping;
-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.EdmSimpleTypeException;
-import org.apache.olingo.odata2.api.edm.EdmSimpleTypeKind;
-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.edm.EdmTyped;
-import org.apache.olingo.odata2.api.ep.EntityProvider;
-import org.apache.olingo.odata2.api.ep.EntityProviderBatchProperties;
-import org.apache.olingo.odata2.api.ep.EntityProviderException;
-import org.apache.olingo.odata2.api.ep.EntityProviderReadProperties;
-import org.apache.olingo.odata2.api.ep.EntityProviderWriteProperties;
-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.ep.entry.ODataEntry;
-import org.apache.olingo.odata2.api.ep.feed.ODataFeed;
-import org.apache.olingo.odata2.api.exception.ODataApplicationException;
-import org.apache.olingo.odata2.api.exception.ODataBadRequestException;
-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.exception.ODataNotImplementedException;
-import org.apache.olingo.odata2.api.processor.ODataContext;
-import org.apache.olingo.odata2.api.processor.ODataRequest;
-import org.apache.olingo.odata2.api.processor.ODataResponse;
-import org.apache.olingo.odata2.api.uri.ExpandSelectTreeNode;
-import org.apache.olingo.odata2.api.uri.KeyPredicate;
-import org.apache.olingo.odata2.api.uri.NavigationSegment;
-import org.apache.olingo.odata2.api.uri.PathInfo;
-import org.apache.olingo.odata2.api.uri.UriParser;
-import org.apache.olingo.odata2.api.uri.expression.BinaryExpression;
-import org.apache.olingo.odata2.api.uri.expression.CommonExpression;
-import org.apache.olingo.odata2.api.uri.expression.ExpressionKind;
-import org.apache.olingo.odata2.api.uri.expression.FilterExpression;
-import org.apache.olingo.odata2.api.uri.expression.LiteralExpression;
-import org.apache.olingo.odata2.api.uri.expression.MemberExpression;
-import org.apache.olingo.odata2.api.uri.expression.MethodExpression;
-import org.apache.olingo.odata2.api.uri.expression.OrderByExpression;
-import org.apache.olingo.odata2.api.uri.expression.OrderExpression;
-import org.apache.olingo.odata2.api.uri.expression.PropertyExpression;
-import org.apache.olingo.odata2.api.uri.expression.SortOrder;
-import org.apache.olingo.odata2.api.uri.expression.UnaryExpression;
-import org.apache.olingo.odata2.api.uri.info.DeleteUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetComplexPropertyUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetEntityCountUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetEntityLinkCountUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetEntityLinkUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetEntitySetCountUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetEntitySetLinksCountUriInfo;
-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.GetMediaResourceUriInfo;
-import org.apache.olingo.odata2.api.uri.info.GetSimplePropertyUriInfo;
-import org.apache.olingo.odata2.api.uri.info.PostUriInfo;
-import org.apache.olingo.odata2.api.uri.info.PutMergePatchUriInfo;
-
-/**
- * Implementation of the centralized parts of OData processing,
- * allowing to use the simplified {@link DataSource} for the
- * actual data handling.
- *
- */
-public class ListsProcessor extends DataSourceProcessor {
-
- // TODO: Paging size should be configurable.
- private static final int SERVER_PAGING_SIZE = 100;
-
- public ListsProcessor(final DataSource dataSource, final ValueAccess valueAccess) {
- super(dataSource, valueAccess);
- }
-
- @Override
- public ODataResponse readEntitySet(final GetEntitySetUriInfo uriInfo, final String contentType)
- throws ODataException {
- ArrayList<Object> data = new ArrayList<Object>();
- try {
- data.addAll((List<?>) retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments()));
- } catch (final ODataNotFoundException e) {
- data.clear();
- }
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
- final InlineCount inlineCountType = uriInfo.getInlineCount();
- final Integer count = applySystemQueryOptions(
- entitySet,
- data,
- uriInfo.getFilter(),
- inlineCountType,
- uriInfo.getOrderBy(),
- uriInfo.getSkipToken(),
- uriInfo.getSkip(),
- uriInfo.getTop());
-
- ODataContext context = getContext();
- String nextLink = null;
-
- // Limit the number of returned entities and provide a "next" link
- // if there are further entities.
- // Almost all system query options in the current request must be carried
- // over to the URI for the "next" link, with the exception of $skiptoken
- // and $skip.
- if (data.size() > SERVER_PAGING_SIZE) {
- if (uriInfo.getOrderBy() == null
- && uriInfo.getSkipToken() == null
- && uriInfo.getSkip() == null
- && uriInfo.getTop() == null) {
- sortInDefaultOrder(entitySet, data);
- }
-
- // TODO: Percent-encode "next" link.
- nextLink = context.getPathInfo().getServiceRoot().relativize(context.getPathInfo().getRequestUri()).toString()
- .replaceAll("\\$skiptoken=.+?&?", "")
- .replaceAll("\\$skip=.+?&?", "")
- .replaceFirst("(?:\\?|&)$", ""); // Remove potentially trailing "?" or "&" left over from remove actions
- // above.
- nextLink += (nextLink.contains("?") ? "&" : "?")
- + "$skiptoken=" + getSkipToken(entitySet, data.get(SERVER_PAGING_SIZE));
-
- while (data.size() > SERVER_PAGING_SIZE) {
- data.remove(SERVER_PAGING_SIZE);
- }
- }
-
- final EdmEntityType entityType = entitySet.getEntityType();
- List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
- for (final Object entryData : data) {
- values.add(getStructuralTypeValueMap(entryData, entityType));
- }
-
- final EntityProviderWriteProperties feedProperties = EntityProviderWriteProperties
- .serviceRoot(context.getPathInfo().getServiceRoot())
- .inlineCountType(inlineCountType)
- .inlineCount(count)
- .expandSelectTree(UriParser.createExpandSelectTree(uriInfo.getSelect(), uriInfo.getExpand()))
- .callbacks(getCallbacks(data, entityType))
- .nextLink(nextLink)
- .build();
-
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeFeed");
- final ODataResponse response = EntityProvider.writeFeed(contentType, entitySet, values, feedProperties);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return ODataResponse.fromResponse(response).build();
- }
-
- @Override
- public ODataResponse countEntitySet(final GetEntitySetCountUriInfo uriInfo, final String contentType)
- throws ODataException {
- ArrayList<Object> data = new ArrayList<Object>();
- try {
- data.addAll((List<?>) retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments()));
- } catch (final ODataNotFoundException e) {
- data.clear();
- }
-
- applySystemQueryOptions(
- uriInfo.getTargetEntitySet(),
- data,
- uriInfo.getFilter(),
- null,
- null,
- null,
- uriInfo.getSkip(),
- uriInfo.getTop());
-
- return ODataResponse.fromResponse(EntityProvider.writeText(String.valueOf(data.size()))).build();
- }
-
- @Override
- public ODataResponse readEntityLinks(final GetEntitySetLinksUriInfo uriInfo, final String contentType)
- throws ODataException {
- ArrayList<Object> data = new ArrayList<Object>();
- try {
- data.addAll((List<?>) retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments()));
- } catch (final ODataNotFoundException e) {
- data.clear();
- }
-
- final Integer count = applySystemQueryOptions(
- uriInfo.getTargetEntitySet(),
- data,
- uriInfo.getFilter(),
- uriInfo.getInlineCount(),
- null, // uriInfo.getOrderBy(),
- uriInfo.getSkipToken(),
- uriInfo.getSkip(),
- uriInfo.getTop());
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
-
- List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
- for (final Object entryData : data) {
- Map<String, Object> entryValues = new HashMap<String, Object>();
- for (final EdmProperty property : entitySet.getEntityType().getKeyProperties()) {
- entryValues.put(property.getName(), valueAccess.getPropertyValue(entryData, property));
- }
- values.add(entryValues);
- }
-
- ODataContext context = getContext();
- final EntityProviderWriteProperties entryProperties = EntityProviderWriteProperties
- .serviceRoot(context.getPathInfo().getServiceRoot())
- .inlineCountType(uriInfo.getInlineCount())
- .inlineCount(count)
- .build();
-
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeLinks");
-
- final ODataResponse response = EntityProvider.writeLinks(contentType, entitySet, values, entryProperties);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return ODataResponse.fromResponse(response).build();
- }
-
- @Override
- public ODataResponse countEntityLinks(final GetEntitySetLinksCountUriInfo uriInfo, final String contentType)
- throws ODataException {
- return countEntitySet((GetEntitySetCountUriInfo) uriInfo, contentType);
- }
-
- @Override
- public ODataResponse readEntity(final GetEntityUriInfo uriInfo, final String contentType) throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final ExpandSelectTreeNode expandSelectTreeNode =
- UriParser.createExpandSelectTree(uriInfo.getSelect(), uriInfo.getExpand());
- ODataResponse odr =
- ODataResponse.fromResponse(writeEntry(uriInfo.getTargetEntitySet(), expandSelectTreeNode, data, contentType))
- .build();
-
- return odr;
- }
-
- @Override
- public ODataResponse existsEntity(final GetEntityCountUriInfo uriInfo, final String contentType)
- throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- return ODataResponse.fromResponse(EntityProvider.writeText(appliesFilter(data, uriInfo.getFilter()) ? "1" : "0"))
- .build();
- }
-
- @Override
- public ODataResponse deleteEntity(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
- dataSource.deleteData(
- uriInfo.getStartEntitySet(),
- mapKey(uriInfo.getKeyPredicates()));
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse createEntity(final PostUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
- final EdmEntityType entityType = entitySet.getEntityType();
-
- Object data = dataSource.newDataObject(entitySet);
- ExpandSelectTreeNode expandSelectTree = null;
-
- if (entityType.hasStream()) {
- dataSource.createData(entitySet, data);
- dataSource.writeBinaryData(entitySet, data,
- new BinaryData(EntityProvider.readBinary(content), requestContentType));
-
- } else {
- final EntityProviderReadProperties properties = EntityProviderReadProperties.init()
- .mergeSemantic(false)
- .addTypeMappings(getStructuralTypeTypeMap(data, entityType))
- .build();
- final ODataEntry entryValues = parseEntry(entitySet, content, requestContentType, properties);
-
- setStructuralTypeValuesFromMap(data, entityType, entryValues.getProperties(), false);
-
- dataSource.createData(entitySet, data);
-
- createInlinedEntities(entitySet, data, entryValues);
-
- expandSelectTree = entryValues.getExpandSelectTree();
- }
-
- // Link back to the entity the target entity set is related to, if any.
- final List<NavigationSegment> navigationSegments = uriInfo.getNavigationSegments();
- if (!navigationSegments.isEmpty()) {
- final List<NavigationSegment> previousSegments = navigationSegments.subList(0, navigationSegments.size() - 1);
- final Object sourceData = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- previousSegments);
- final EdmEntitySet previousEntitySet = previousSegments.isEmpty() ?
- uriInfo.getStartEntitySet() : previousSegments.get(previousSegments.size() - 1).getEntitySet();
- dataSource.writeRelation(previousEntitySet, sourceData, entitySet, getStructuralTypeValueMap(data, entityType));
- }
-
- return ODataResponse.fromResponse(writeEntry(uriInfo.getTargetEntitySet(), expandSelectTree, data, contentType))
- .eTag(constructETag(entitySet, data)).build();
- }
-
- @Override
- public ODataResponse updateEntity(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final boolean merge, final String contentType) throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
- final EdmEntityType entityType = entitySet.getEntityType();
- final EntityProviderReadProperties properties = EntityProviderReadProperties.init()
- .mergeSemantic(merge)
- .addTypeMappings(getStructuralTypeTypeMap(data, entityType))
- .build();
- final ODataEntry entryValues = parseEntry(entitySet, content, requestContentType, properties);
-
- setStructuralTypeValuesFromMap(data, entityType, entryValues.getProperties(), merge);
-
- return ODataResponse.newBuilder().eTag(constructETag(entitySet, data)).build();
- }
-
- @Override
- public ODataResponse readEntityLink(final GetEntityLinkUriInfo uriInfo, final String contentType)
- throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- // if (!appliesFilter(data, uriInfo.getFilter()))
- if (data == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
-
- Map<String, Object> values = new HashMap<String, Object>();
- for (final EdmProperty property : entitySet.getEntityType().getKeyProperties()) {
- values.put(property.getName(), valueAccess.getPropertyValue(data, property));
- }
-
- ODataContext context = getContext();
- final EntityProviderWriteProperties entryProperties = EntityProviderWriteProperties
- .serviceRoot(context.getPathInfo().getServiceRoot())
- .build();
-
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeLink");
-
- final ODataResponse response = EntityProvider.writeLink(contentType, entitySet, values, entryProperties);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return ODataResponse.fromResponse(response).build();
- }
-
- @Override
- public ODataResponse existsEntityLink(final GetEntityLinkCountUriInfo uriInfo, final String contentType)
- throws ODataException {
- return existsEntity((GetEntityCountUriInfo) uriInfo, contentType);
- }
-
- @Override
- public ODataResponse deleteEntityLink(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
- final List<NavigationSegment> navigationSegments = uriInfo.getNavigationSegments();
- final List<NavigationSegment> previousSegments = navigationSegments.subList(0, navigationSegments.size() - 1);
-
- final Object sourceData = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- previousSegments);
-
- final EdmEntitySet entitySet = previousSegments.isEmpty() ?
- uriInfo.getStartEntitySet() : previousSegments.get(previousSegments.size() - 1).getEntitySet();
- final EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
- final Map<String, Object> keys = mapKey(uriInfo.getTargetKeyPredicates());
-
- final Object targetData = dataSource.readRelatedData(entitySet, sourceData, targetEntitySet, keys);
-
- // if (!appliesFilter(targetData, uriInfo.getFilter()))
- if (targetData == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- dataSource.deleteRelation(entitySet, sourceData, targetEntitySet, keys);
-
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse createEntityLink(final PostUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- final List<NavigationSegment> navigationSegments = uriInfo.getNavigationSegments();
- final List<NavigationSegment> previousSegments = navigationSegments.subList(0, navigationSegments.size() - 1);
-
- final Object sourceData = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- previousSegments);
-
- final EdmEntitySet entitySet = previousSegments.isEmpty() ?
- uriInfo.getStartEntitySet() : previousSegments.get(previousSegments.size() - 1).getEntitySet();
- final EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
-
- final Map<String, Object> targetKeys = parseLink(targetEntitySet, content, requestContentType);
-
- dataSource.writeRelation(entitySet, sourceData, targetEntitySet, targetKeys);
-
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse updateEntityLink(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- final List<NavigationSegment> navigationSegments = uriInfo.getNavigationSegments();
- final List<NavigationSegment> previousSegments = navigationSegments.subList(0, navigationSegments.size() - 1);
-
- final Object sourceData = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- previousSegments);
-
- final EdmEntitySet entitySet = previousSegments.isEmpty() ?
- uriInfo.getStartEntitySet() : previousSegments.get(previousSegments.size() - 1).getEntitySet();
- final EdmEntitySet targetEntitySet = uriInfo.getTargetEntitySet();
- final Map<String, Object> keys = mapKey(uriInfo.getTargetKeyPredicates());
-
- final Object targetData = dataSource.readRelatedData(entitySet, sourceData, targetEntitySet, keys);
-
- if (!appliesFilter(targetData, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- dataSource.deleteRelation(entitySet, sourceData, targetEntitySet, keys);
-
- final Map<String, Object> newKeys = parseLink(targetEntitySet, content, requestContentType);
-
- dataSource.writeRelation(entitySet, sourceData, targetEntitySet, newKeys);
-
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse readEntityComplexProperty(final GetComplexPropertyUriInfo uriInfo, final String contentType)
- throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- // if (!appliesFilter(data, uriInfo.getFilter()))
- if (data == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
- final Object value = property.isSimple() ?
- property.getMapping() == null || property.getMapping().getMimeType() == null ?
- getPropertyValue(data, propertyPath) : getSimpleTypeValueMap(data, propertyPath) :
- getStructuralTypeValueMap(getPropertyValue(data, propertyPath), (EdmStructuralType) property.getType());
-
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeProperty");
-
- final ODataResponse response = EntityProvider.writeProperty(contentType, property, value);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return ODataResponse.fromResponse(response).eTag(constructETag(uriInfo.getTargetEntitySet(), data)).build();
- }
-
- @Override
- public ODataResponse readEntitySimpleProperty(final GetSimplePropertyUriInfo uriInfo, final String contentType)
- throws ODataException {
- return readEntityComplexProperty((GetComplexPropertyUriInfo) uriInfo, contentType);
- }
-
- @Override
- public ODataResponse readEntitySimplePropertyValue(final GetSimplePropertyUriInfo uriInfo, final String contentType)
- throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- // if (!appliesFilter(data, uriInfo.getFilter()))
- if (data == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
- final Object value = property.getMapping() == null || property.getMapping().getMimeType() == null ?
- getPropertyValue(data, propertyPath) : getSimpleTypeValueMap(data, propertyPath);
-
- return ODataResponse.fromResponse(EntityProvider.writePropertyValue(property, value)).eTag(
- constructETag(uriInfo.getTargetEntitySet(), data)).build();
- }
-
- @Override
- public ODataResponse deleteEntitySimplePropertyValue(final DeleteUriInfo uriInfo, final String contentType)
- throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (data == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
-
- data = getPropertyValue(data, propertyPath.subList(0, propertyPath.size() - 1));
- valueAccess.setPropertyValue(data, property, null);
- valueAccess.setMappingValue(data, property.getMapping(), null);
-
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse updateEntityComplexProperty(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final boolean merge, final String contentType) throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
-
- data = getPropertyValue(data, propertyPath.subList(0, propertyPath.size() - 1));
-
- ODataContext context = getContext();
- int timingHandle = context.startRuntimeMeasurement("EntityConsumer", "readProperty");
-
- Map<String, Object> values;
- try {
- values =
- EntityProvider.readProperty(requestContentType, property, content, EntityProviderReadProperties.init()
- .mergeSemantic(merge).build());
- } catch (final EntityProviderException e) {
- throw new ODataBadRequestException(ODataBadRequestException.BODY, e);
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- final Object value = values.get(property.getName());
- if (property.isSimple()) {
- valueAccess.setPropertyValue(data, property, value);
- } else {
- @SuppressWarnings("unchecked")
- final Map<String, Object> propertyValue = (Map<String, Object>) value;
- setStructuralTypeValuesFromMap(valueAccess.getPropertyValue(data, property),
- (EdmStructuralType) property.getType(), propertyValue, merge);
- }
-
- return ODataResponse.newBuilder().eTag(constructETag(uriInfo.getTargetEntitySet(), data)).build();
- }
-
- @Override
- public ODataResponse updateEntitySimpleProperty(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- return updateEntityComplexProperty(uriInfo, content, requestContentType, false, contentType);
- }
-
- @Override
- public ODataResponse updateEntitySimplePropertyValue(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final List<EdmProperty> propertyPath = uriInfo.getPropertyPath();
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
-
- data = getPropertyValue(data, propertyPath.subList(0, propertyPath.size() - 1));
-
- ODataContext context = getContext();
- int timingHandle = context.startRuntimeMeasurement("EntityConsumer", "readPropertyValue");
-
- Object value;
- try {
- value = EntityProvider.readPropertyValue(property, content);
- } catch (final EntityProviderException e) {
- throw new ODataBadRequestException(ODataBadRequestException.BODY, e);
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- valueAccess.setPropertyValue(data, property, value);
- valueAccess.setMappingValue(data, property.getMapping(), requestContentType);
-
- return ODataResponse.newBuilder().eTag(constructETag(uriInfo.getTargetEntitySet(), data)).build();
- }
-
- @Override
- public ODataResponse readEntityMedia(final GetMediaResourceUriInfo uriInfo, final String contentType)
- throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
- final BinaryData binaryData = dataSource.readBinaryData(entitySet, data);
- if (binaryData == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- final String mimeType = binaryData.getMimeType() == null ?
- HttpContentType.APPLICATION_OCTET_STREAM : binaryData.getMimeType();
-
- return ODataResponse.fromResponse(EntityProvider.writeBinary(mimeType, binaryData.getData())).eTag(
- constructETag(entitySet, data)).build();
- }
-
- @Override
- public ODataResponse deleteEntityMedia(final DeleteUriInfo uriInfo, final String contentType) throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (data == null) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- dataSource.writeBinaryData(uriInfo.getTargetEntitySet(), data, new BinaryData(null, null));
-
- return ODataResponse.newBuilder().build();
- }
-
- @Override
- public ODataResponse updateEntityMedia(final PutMergePatchUriInfo uriInfo, final InputStream content,
- final String requestContentType, final String contentType) throws ODataException {
- final Object data = retrieveData(
- uriInfo.getStartEntitySet(),
- uriInfo.getKeyPredicates(),
- uriInfo.getFunctionImport(),
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- uriInfo.getNavigationSegments());
-
- if (!appliesFilter(data, uriInfo.getFilter())) {
- throw new ODataNotFoundException(ODataNotFoundException.ENTITY);
- }
-
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "readBinary");
-
- final byte[] value = EntityProvider.readBinary(content);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- final EdmEntitySet entitySet = uriInfo.getTargetEntitySet();
- dataSource.writeBinaryData(entitySet, data, new BinaryData(value, requestContentType));
-
- return ODataResponse.newBuilder().eTag(constructETag(entitySet, data)).build();
- }
-
- @Override
- public ODataResponse executeFunctionImport(final GetFunctionImportUriInfo uriInfo, final String contentType)
- throws ODataException {
- final EdmFunctionImport functionImport = uriInfo.getFunctionImport();
- final EdmType type = functionImport.getReturnType().getType();
-
- final Object data = dataSource.readData(
- functionImport,
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- null);
-
- if (data == null) {
- throw new ODataNotFoundException(ODataHttpException.COMMON);
- }
-
- Object value;
- if (type.getKind() == EdmTypeKind.SIMPLE) {
- value = type == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance() ?
- ((BinaryData) data).getData() : data;
- } else if (functionImport.getReturnType().getMultiplicity() == EdmMultiplicity.MANY) {
- List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
- for (final Object typeData : (List<?>) data) {
- values.add(getStructuralTypeValueMap(typeData, (EdmStructuralType) type));
- }
- value = values;
- } else {
- value = getStructuralTypeValueMap(data, (EdmStructuralType) type);
- }
-
- ODataContext context = getContext();
-
- final EntityProviderWriteProperties entryProperties = EntityProviderWriteProperties
- .serviceRoot(context.getPathInfo().getServiceRoot()).build();
-
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeFunctionImport");
-
- final ODataResponse response =
- EntityProvider.writeFunctionImport(contentType, functionImport, value, entryProperties);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return ODataResponse.fromResponse(response).build();
- }
-
- @Override
- public ODataResponse executeFunctionImportValue(final GetFunctionImportUriInfo uriInfo, final String contentType)
- throws ODataException {
- final EdmFunctionImport functionImport = uriInfo.getFunctionImport();
- final EdmSimpleType type = (EdmSimpleType) functionImport.getReturnType().getType();
-
- final Object data = dataSource.readData(
- functionImport,
- mapFunctionParameters(uriInfo.getFunctionImportParameters()),
- null);
-
- if (data == null) {
- throw new ODataNotFoundException(ODataHttpException.COMMON);
- }
-
- ODataResponse response;
- if (type == EdmSimpleTypeKind.Binary.getEdmSimpleTypeInstance()) {
- response = EntityProvider.writeBinary(((BinaryData) data).getMimeType(), ((BinaryData) data).getData());
- } else {
- final String value = type.valueToString(data, EdmLiteralKind.DEFAULT, null);
- response = EntityProvider.writeText(value == null ? "" : value);
- }
- return ODataResponse.fromResponse(response).build();
- }
-
- private static Map<String, Object> mapKey(final List<KeyPredicate> keys) throws EdmException {
- Map<String, Object> keyMap = new HashMap<String, Object>();
- for (final KeyPredicate key : keys) {
- final EdmProperty property = key.getProperty();
- final EdmSimpleType type = (EdmSimpleType) property.getType();
- keyMap.put(property.getName(), type.valueOfString(key.getLiteral(), EdmLiteralKind.DEFAULT, property.getFacets(),
- type.getDefaultType()));
- }
- return keyMap;
- }
-
- private static Map<String, Object> mapFunctionParameters(final Map<String, EdmLiteral> functionImportParameters)
- throws EdmSimpleTypeException {
- if (functionImportParameters == null) {
- return Collections.emptyMap();
- } else {
- Map<String, Object> parameterMap = new HashMap<String, Object>();
- for (final String parameterName : functionImportParameters.keySet()) {
- final EdmLiteral literal = functionImportParameters.get(parameterName);
- final EdmSimpleType type = literal.getType();
- parameterMap.put(parameterName, type.valueOfString(literal.getLiteral(), EdmLiteralKind.DEFAULT, null, type
- .getDefaultType()));
- }
- return parameterMap;
- }
- }
-
- private Object retrieveData(final EdmEntitySet startEntitySet, final List<KeyPredicate> keyPredicates,
- final EdmFunctionImport functionImport, final Map<String, Object> functionImportParameters,
- final List<NavigationSegment> navigationSegments) throws ODataException {
- Object data;
- final Map<String, Object> keys = mapKey(keyPredicates);
-
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "retrieveData");
-
- data = functionImport == null ?
- keys.isEmpty() ?
- dataSource.readData(startEntitySet) : dataSource.readData(startEntitySet, keys) :
- dataSource.readData(functionImport, functionImportParameters, keys);
-
- EdmEntitySet currentEntitySet =
- functionImport == null ? startEntitySet : functionImport.getEntitySet();
- for (NavigationSegment navigationSegment : navigationSegments) {
- data = dataSource.readRelatedData(
- currentEntitySet,
- data,
- navigationSegment.getEntitySet(),
- mapKey(navigationSegment.getKeyPredicates()));
- currentEntitySet = navigationSegment.getEntitySet();
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return data;
- }
-
- private <T> String constructETag(final EdmEntitySet entitySet, final T data) throws ODataException {
- final EdmEntityType entityType = entitySet.getEntityType();
- String eTag = null;
- for (final String propertyName : entityType.getPropertyNames()) {
- final EdmProperty property = (EdmProperty) entityType.getProperty(propertyName);
- if (property.getFacets() != null && property.getFacets().getConcurrencyMode() == EdmConcurrencyMode.Fixed) {
- final EdmSimpleType type = (EdmSimpleType) property.getType();
- final String component = type.valueToString(valueAccess.getPropertyValue(data, property),
- EdmLiteralKind.DEFAULT, property.getFacets());
- eTag = eTag == null ? component : eTag + Edm.DELIMITER + component;
- }
- }
- return eTag == null ? null : "W/\"" + eTag + "\"";
- }
-
- private <T> Map<String, ODataCallback> getCallbacks(final T data, final EdmEntityType entityType)
- throws EdmException {
- final List<String> navigationPropertyNames = entityType.getNavigationPropertyNames();
- if (navigationPropertyNames.isEmpty()) {
- return null;
- } else {
- final WriteCallback callback = new WriteCallback(data);
- Map<String, ODataCallback> callbacks = new HashMap<String, ODataCallback>();
- for (final String name : navigationPropertyNames) {
- callbacks.put(name, callback);
- }
- return callbacks;
- }
- }
-
- private class WriteCallback implements OnWriteEntryContent, OnWriteFeedContent {
- private final Object data;
-
- private <T> WriteCallback(final T data) {
- this.data = data;
- }
-
- @Override
- public WriteFeedCallbackResult retrieveFeedResult(final WriteFeedCallbackContext context)
- throws ODataApplicationException {
- try {
- final EdmEntityType entityType =
- context.getSourceEntitySet().getRelatedEntitySet(context.getNavigationProperty()).getEntityType();
- List<Map<String, Object>> values = new ArrayList<Map<String, Object>>();
- Object relatedData = null;
- try {
- relatedData = readRelatedData(context);
- for (final Object entryData : (List<?>) relatedData) {
- values.add(getStructuralTypeValueMap(entryData, entityType));
- }
- } catch (final ODataNotFoundException e) {
- values.clear();
- }
- WriteFeedCallbackResult result = new WriteFeedCallbackResult();
- result.setFeedData(values);
- EntityProviderWriteProperties inlineProperties =
- EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).callbacks(
- getCallbacks(relatedData, entityType)).expandSelectTree(context.getCurrentExpandSelectTreeNode())
- .selfLink(context.getSelfLink()).build();
- result.setInlineProperties(inlineProperties);
- return result;
- } catch (final ODataException e) {
- throw new ODataApplicationException(e.getLocalizedMessage(), Locale.ROOT, e);
- }
- }
-
- @Override
- public WriteEntryCallbackResult retrieveEntryResult(final WriteEntryCallbackContext context)
- throws ODataApplicationException {
- try {
- final EdmEntityType entityType =
- context.getSourceEntitySet().getRelatedEntitySet(context.getNavigationProperty()).getEntityType();
- WriteEntryCallbackResult result = new WriteEntryCallbackResult();
- Object relatedData;
- try {
- relatedData = readRelatedData(context);
- } catch (final ODataNotFoundException e) {
- relatedData = null;
- }
-
- if (relatedData == null) {
- result.setEntryData(Collections.<String, Object> emptyMap());
- } else {
- result.setEntryData(getStructuralTypeValueMap(relatedData, entityType));
-
- EntityProviderWriteProperties inlineProperties =
- EntityProviderWriteProperties.serviceRoot(getContext().getPathInfo().getServiceRoot()).callbacks(
- getCallbacks(relatedData, entityType)).expandSelectTree(context.getCurrentExpandSelectTreeNode())
- .build();
- result.setInlineProperties(inlineProperties);
- }
- return result;
- } catch (final ODataException e) {
- throw new ODataApplicationException(e.getLocalizedMessage(), Locale.ROOT, e);
- }
- }
-
- private Object readRelatedData(final WriteCallbackContext context) throws ODataException {
- final EdmEntitySet entitySet = context.getSourceEntitySet();
- return dataSource.readRelatedData(
- entitySet,
- data instanceof List ? readEntryData((List<?>) data, entitySet.getEntityType(), context
- .extractKeyFromEntryData()) : data,
- entitySet.getRelatedEntitySet(context.getNavigationProperty()),
- Collections.<String, Object> emptyMap());
- }
-
- private <T> T readEntryData(final List<T> data, final EdmEntityType entityType, final Map<String, Object> key)
- throws ODataException {
- for (final T entryData : data) {
- boolean found = true;
- for (final EdmProperty keyProperty : entityType.getKeyProperties()) {
- if (!valueAccess.getPropertyValue(entryData, keyProperty).equals(key.get(keyProperty.getName()))) {
- found = false;
- break;
- }
- }
- if (found) {
- return entryData;
- }
- }
- return null;
- }
- }
-
- private <T> ODataResponse writeEntry(final EdmEntitySet entitySet, final ExpandSelectTreeNode expandSelectTree,
- final T data, final String contentType) throws ODataException, EntityProviderException {
- final EdmEntityType entityType = entitySet.getEntityType();
- final Map<String, Object> values = getStructuralTypeValueMap(data, entityType);
-
- ODataContext context = getContext();
- EntityProviderWriteProperties writeProperties = EntityProviderWriteProperties
- .serviceRoot(context.getPathInfo().getServiceRoot())
- .expandSelectTree(expandSelectTree)
- .callbacks(getCallbacks(data, entityType))
- .build();
-
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "writeEntry");
-
- final ODataResponse response = EntityProvider.writeEntry(contentType, entitySet, values, writeProperties);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return response;
- }
-
- private ODataEntry parseEntry(final EdmEntitySet entitySet, final InputStream content,
- final String requestContentType, final EntityProviderReadProperties properties) throws ODataBadRequestException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement("EntityConsumer", "readEntry");
-
- ODataEntry entryValues;
- try {
- entryValues = EntityProvider.readEntry(requestContentType, entitySet, content, properties);
- } catch (final EntityProviderException e) {
- throw new ODataBadRequestException(ODataBadRequestException.BODY, e);
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return entryValues;
- }
-
- private Map<String, Object> parseLink(final EdmEntitySet entitySet, final InputStream content,
- final String contentType) throws ODataException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement("EntityProvider", "readLink");
-
- final String uriString = EntityProvider.readLink(contentType, entitySet, content);
-
- context.stopRuntimeMeasurement(timingHandle);
-
- final Map<String, Object> targetKeys = parseLinkUri(entitySet, uriString);
- if (targetKeys == null) {
- throw new ODataBadRequestException(ODataBadRequestException.BODY);
- }
- return targetKeys;
- }
-
- private Map<String, Object> parseLinkUri(final EdmEntitySet targetEntitySet, final String uriString)
- throws EdmException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement("UriParser", "getKeyPredicatesFromEntityLink");
-
- List<KeyPredicate> key = null;
- try {
- key = UriParser.getKeyPredicatesFromEntityLink(targetEntitySet, uriString,
- context.getPathInfo().getServiceRoot());
- } catch (ODataException e) {
- // We don't understand the link target. This could also be seen as an error.
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return key == null ? null : mapKey(key);
- }
-
- private <T> void createInlinedEntities(final EdmEntitySet entitySet, final T data, final ODataEntry entryValues)
- throws ODataException {
- final EdmEntityType entityType = entitySet.getEntityType();
- for (final String navigationPropertyName : entityType.getNavigationPropertyNames()) {
-
- final EdmNavigationProperty navigationProperty =
- (EdmNavigationProperty) entityType.getProperty(navigationPropertyName);
- final EdmEntitySet relatedEntitySet = entitySet.getRelatedEntitySet(navigationProperty);
- final EdmEntityType relatedEntityType = relatedEntitySet.getEntityType();
-
- final Object relatedValue = entryValues.getProperties().get(navigationPropertyName);
- if (relatedValue == null) {
- for (final String uriString : entryValues.getMetadata().getAssociationUris(navigationPropertyName)) {
- final Map<String, Object> key = parseLinkUri(relatedEntitySet, uriString);
- if (key != null) {
- dataSource.writeRelation(entitySet, data, relatedEntitySet, key);
- }
- }
-
- } else {
- if (relatedValue instanceof ODataFeed) {
- ODataFeed feed = (ODataFeed) relatedValue;
- final List<ODataEntry> relatedValueList = feed.getEntries();
- for (final ODataEntry relatedValues : relatedValueList) {
- Object relatedData = dataSource.newDataObject(relatedEntitySet);
- setStructuralTypeValuesFromMap(relatedData, relatedEntityType, relatedValues.getProperties(), false);
- dataSource.createData(relatedEntitySet, relatedData);
- dataSource.writeRelation(entitySet, data, relatedEntitySet, getStructuralTypeValueMap(relatedData,
- relatedEntityType));
- createInlinedEntities(relatedEntitySet, relatedData, relatedValues);
- }
- } else if (relatedValue instanceof ODataEntry) {
- final ODataEntry relatedValueEntry = (ODataEntry) relatedValue;
- Object relatedData = dataSource.newDataObject(relatedEntitySet);
- setStructuralTypeValuesFromMap(relatedData, relatedEntityType, relatedValueEntry.getProperties(), false);
- dataSource.createData(relatedEntitySet, relatedData);
- dataSource.writeRelation(entitySet, data, relatedEntitySet, getStructuralTypeValueMap(relatedData,
- relatedEntityType));
- createInlinedEntities(relatedEntitySet, relatedData, relatedValueEntry);
- } else {
- throw new ODataException("Unexpected class for a related value: " + relatedValue.getClass().getSimpleName());
- }
-
- }
- }
- }
-
- private <T> Integer applySystemQueryOptions(final EdmEntitySet entitySet, final List<T> data,
- final FilterExpression filter, final InlineCount inlineCount, final OrderByExpression orderBy,
- final String skipToken, final Integer skip, final Integer top) throws ODataException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "applySystemQueryOptions");
-
- if (filter != null) {
- // Remove all elements the filter does not apply for.
- // A for-each loop would not work with "remove", see Java documentation.
- for (Iterator<T> iterator = data.iterator(); iterator.hasNext();) {
- if (!appliesFilter(iterator.next(), filter)) {
- iterator.remove();
- }
- }
- }
-
- final Integer count = inlineCount == InlineCount.ALLPAGES ? data.size() : null;
-
- if (orderBy != null) {
- sort(data, orderBy);
- } else if (skipToken != null || skip != null || top != null) {
- sortInDefaultOrder(entitySet, data);
- }
-
- if (skipToken != null) {
- while (!data.isEmpty() && !getSkipToken(entitySet, data.get(0)).equals(skipToken)) {
- data.remove(0);
- }
- }
-
- if (skip != null) {
- if (skip >= data.size()) {
- data.clear();
- } else {
- for (int i = 0; i < skip; i++) {
- data.remove(0);
- }
- }
- }
-
- if (top != null) {
- while (data.size() > top) {
- data.remove(top.intValue());
- }
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return count;
- }
-
- private <T> void sort(final List<T> data, final OrderByExpression orderBy) {
- Collections.sort(data, new Comparator<T>() {
- @Override
- public int compare(final T entity1, final T entity2) {
- try {
- int result = 0;
- for (final OrderExpression expression : orderBy.getOrders()) {
- result = evaluateExpression(entity1, expression.getExpression()).compareTo(
- evaluateExpression(entity2, expression.getExpression()));
- if (expression.getSortOrder() == SortOrder.desc) {
- result = -result;
- }
- if (result != 0) {
- break;
- }
- }
- return result;
- } catch (final ODataException e) {
- return 0;
- }
- }
- });
- }
-
- private <T> void sortInDefaultOrder(final EdmEntitySet entitySet, final List<T> data) {
- Collections.sort(data, new Comparator<T>() {
- @Override
- public int compare(final T entity1, final T entity2) {
- try {
- return getSkipToken(entitySet, entity1).compareTo(getSkipToken(entitySet, entity2));
- } catch (final ODataException e) {
- return 0;
- }
- }
- });
- }
-
- private <T> boolean appliesFilter(final T data, final FilterExpression filter) throws ODataException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "appliesFilter");
-
- try {
- return data != null && (filter == null || evaluateExpression(data, filter.getExpression()).equals("true"));
- } catch (final RuntimeException e) {
- return false;
- } finally {
- context.stopRuntimeMeasurement(timingHandle);
- }
- }
-
- private <T> String evaluateExpression(final T data, final CommonExpression expression) throws ODataException {
- switch (expression.getKind()) {
- case UNARY:
- final UnaryExpression unaryExpression = (UnaryExpression) expression;
- final String operand = evaluateExpression(data, unaryExpression.getOperand());
-
- switch (unaryExpression.getOperator()) {
- case NOT:
- return Boolean.toString(!Boolean.parseBoolean(operand));
- case MINUS:
- return operand.startsWith("-") ? operand.substring(1) : "-" + operand;
- default:
- throw new ODataNotImplementedException();
- }
-
- case BINARY:
- final BinaryExpression binaryExpression = (BinaryExpression) expression;
- final EdmSimpleType type = (EdmSimpleType) binaryExpression.getLeftOperand().getEdmType();
- final String left = evaluateExpression(data, binaryExpression.getLeftOperand());
- final String right = evaluateExpression(data, binaryExpression.getRightOperand());
-
- switch (binaryExpression.getOperator()) {
- case ADD:
- if (binaryExpression.getEdmType() == EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
- return Double.toString(Double.valueOf(left) + Double.valueOf(right));
- } else {
- return Long.toString(Long.valueOf(left) + Long.valueOf(right));
- }
- case SUB:
- if (binaryExpression.getEdmType() == EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
- return Double.toString(Double.valueOf(left) - Double.valueOf(right));
- } else {
- return Long.toString(Long.valueOf(left) - Long.valueOf(right));
- }
- case MUL:
- if (binaryExpression.getEdmType() == EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
- return Double.toString(Double.valueOf(left) * Double.valueOf(right));
- } else {
- return Long.toString(Long.valueOf(left) * Long.valueOf(right));
- }
- case DIV:
- final String number = Double.toString(Double.valueOf(left) / Double.valueOf(right));
- return number.endsWith(".0") ? number.replace(".0", "") : number;
- case MODULO:
- if (binaryExpression.getEdmType() == EdmSimpleTypeKind.Decimal.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Double.getEdmSimpleTypeInstance()
- || binaryExpression.getEdmType() == EdmSimpleTypeKind.Single.getEdmSimpleTypeInstance()) {
- return Double.toString(Double.valueOf(left) % Double.valueOf(right));
- } else {
- return Long.toString(Long.valueOf(left) % Long.valueOf(right));
- }
- case AND:
- return Boolean.toString(left.equals("true") && right.equals("true"));
- case OR:
- return Boolean.toString(left.equals("true") || right.equals("true"));
- case EQ:
- return Boolean.toString(left.equals(right));
- case NE:
- return Boolean.toString(!left.equals(right));
- case LT:
- if (type == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
- return Boolean.toString(left.compareTo(right) < 0);
- } else {
- return Boolean.toString(Double.valueOf(left) < Double.valueOf(right));
- }
- case LE:
- if (type == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
- return Boolean.toString(left.compareTo(right) <= 0);
- } else {
- return Boolean.toString(Double.valueOf(left) <= Double.valueOf(right));
- }
- case GT:
- if (type == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
- return Boolean.toString(left.compareTo(right) > 0);
- } else {
- return Boolean.toString(Double.valueOf(left) > Double.valueOf(right));
- }
- case GE:
- if (type == EdmSimpleTypeKind.String.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTime.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.DateTimeOffset.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Guid.getEdmSimpleTypeInstance()
- || type == EdmSimpleTypeKind.Time.getEdmSimpleTypeInstance()) {
- return Boolean.toString(left.compareTo(right) >= 0);
- } else {
- return Boolean.toString(Double.valueOf(left) >= Double.valueOf(right));
- }
- case PROPERTY_ACCESS:
- throw new ODataNotImplementedException();
- default:
- throw new ODataNotImplementedException();
- }
-
- case PROPERTY:
- final EdmProperty property = (EdmProperty) ((PropertyExpression) expression).getEdmProperty();
- final EdmSimpleType propertyType = (EdmSimpleType) property.getType();
- return propertyType.valueToString(valueAccess.getPropertyValue(data, property), EdmLiteralKind.DEFAULT,
- property.getFacets());
-
- case MEMBER:
- final MemberExpression memberExpression = (MemberExpression) expression;
- final PropertyExpression propertyExpression = (PropertyExpression) memberExpression.getProperty();
- final EdmProperty memberProperty = (EdmProperty) propertyExpression.getEdmProperty();
- final EdmSimpleType memberType = (EdmSimpleType) memberExpression.getEdmType();
- List<EdmProperty> propertyPath = new ArrayList<EdmProperty>();
- CommonExpression currentExpression = memberExpression;
- while (currentExpression != null) {
- final PropertyExpression currentPropertyExpression =
- (PropertyExpression) (currentExpression.getKind() == ExpressionKind.MEMBER ?
- ((MemberExpression) currentExpression).getProperty() : currentExpression);
- final EdmTyped currentProperty = currentPropertyExpression.getEdmProperty();
- final EdmTypeKind kind = currentProperty.getType().getKind();
- if (kind == EdmTypeKind.SIMPLE || kind == EdmTypeKind.COMPLEX) {
- propertyPath.add(0, (EdmProperty) currentProperty);
- } else {
- throw new ODataNotImplementedException();
- }
- currentExpression =
- currentExpression.getKind() == ExpressionKind.MEMBER ? ((MemberExpression) currentExpression).getPath()
- : null;
- }
- return memberType.valueToString(getPropertyValue(data, propertyPath), EdmLiteralKind.DEFAULT, memberProperty
- .getFacets());
-
- case LITERAL:
- final LiteralExpression literal = (LiteralExpression) expression;
- final EdmSimpleType literalType = (EdmSimpleType) literal.getEdmType();
- return literalType.valueToString(literalType.valueOfString(literal.getUriLiteral(), EdmLiteralKind.URI, null,
- literalType.getDefaultType()),
- EdmLiteralKind.DEFAULT, null);
-
- case METHOD:
- final MethodExpression methodExpression = (MethodExpression) expression;
- final String first = evaluateExpression(data, methodExpression.getParameters().get(0));
- final String second = methodExpression.getParameterCount() > 1 ?
- evaluateExpression(data, methodExpression.getParameters().get(1)) : null;
- final String third = methodExpression.getParameterCount() > 2 ?
- evaluateExpression(data, methodExpression.getParameters().get(2)) : null;
-
- switch (methodExpression.getMethod()) {
- case ENDSWITH:
- return Boolean.toString(first.endsWith(second));
- case INDEXOF:
- return Integer.toString(first.indexOf(second));
- case STARTSWITH:
- return Boolean.toString(first.startsWith(second));
- case TOLOWER:
- return first.toLowerCase(Locale.ROOT);
- case TOUPPER:
- return first.toUpperCase(Locale.ROOT);
- case TRIM:
- return first.trim();
- case SUBSTRING:
- final int offset = Integer.parseInt(second);
- return first.substring(offset, offset + Integer.parseInt(third));
- case SUBSTRINGOF:
- return Boolean.toString(second.contains(first));
- case CONCAT:
- return first + second;
- case LENGTH:
- return Integer.toString(first.length());
- case YEAR:
- return String.valueOf(Integer.parseInt(first.substring(0, 4)));
- case MONTH:
- return String.valueOf(Integer.parseInt(first.substring(5, 7)));
- case DAY:
- return String.valueOf(Integer.parseInt(first.substring(8, 10)));
- case HOUR:
- return String.valueOf(Integer.parseInt(first.substring(11, 13)));
- case MINUTE:
- return String.valueOf(Integer.parseInt(first.substring(14, 16)));
- case SECOND:
- return String.valueOf(Integer.parseInt(first.substring(17, 19)));
- case ROUND:
- return Long.toString(Math.round(Double.valueOf(first)));
- case FLOOR:
- return Long.toString(Math.round(Math.floor(Double.valueOf(first))));
- case CEILING:
- return Long.toString(Math.round(Math.ceil(Double.valueOf(first))));
- default:
- throw new ODataNotImplementedException();
- }
-
- default:
- throw new ODataNotImplementedException();
- }
- }
-
- private <T> String getSkipToken(final EdmEntitySet entitySet, final T data) throws ODataException {
- String skipToken = "";
- for (final EdmProperty property : entitySet.getEntityType().getKeyProperties()) {
- final EdmSimpleType type = (EdmSimpleType) property.getType();
- skipToken = skipToken.concat(type.valueToString(valueAccess.getPropertyValue(data, property),
- EdmLiteralKind.DEFAULT, property.getFacets()));
- }
- return skipToken;
- }
-
- private <T> Object getPropertyValue(final T data, final List<EdmProperty> propertyPath) throws ODataException {
- Object dataObject = data;
- for (final EdmProperty property : propertyPath) {
- if (dataObject != null) {
- dataObject = valueAccess.getPropertyValue(dataObject, property);
- }
- }
- return dataObject;
- }
-
- private void handleMimeType(Object data, EdmMapping mapping, Map<String, Object> valueMap)
- throws ODataException {
- final String mimeTypeName = mapping.getMimeType();
- if (mimeTypeName != null) {
- Object value = valueAccess.getMappingValue(data, mapping);
- valueMap.put(mimeTypeName, value);
- if (mapping.getMediaResourceMimeTypeKey() != null) {
- valueMap.put(mapping.getMediaResourceMimeTypeKey(), value);
- }
- }
- }
-
- private <T> Map<String, Object> getSimpleTypeValueMap(final T data, final List<EdmProperty> propertyPath)
- throws ODataException {
- final EdmProperty property = propertyPath.get(propertyPath.size() - 1);
- Map<String, Object> valueWithMimeType = new HashMap<String, Object>();
- valueWithMimeType.put(property.getName(), getPropertyValue(data, propertyPath));
-
- handleMimeType(data, property.getMapping(), valueWithMimeType);
-
- return valueWithMimeType;
- }
-
- private <T> Map<String, Object> getStructuralTypeValueMap(final T data, final EdmStructuralType type)
- throws ODataException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "getStructuralTypeValueMap");
-
- Map<String, Object> valueMap = new HashMap<String, Object>();
-
- EdmMapping mapping = type.getMapping();
- if (mapping != null) {
- handleMimeType(data, mapping, valueMap);
- }
-
- for (final String propertyName : type.getPropertyNames()) {
- final EdmProperty property = (EdmProperty) type.getProperty(propertyName);
- final Object value = valueAccess.getPropertyValue(data, property);
-
- if (property.isSimple()) {
- if (property.getMapping() == null || property.getMapping().getMimeType() == null) {
- valueMap.put(propertyName, value);
- } else {
- // TODO: enable MIME type mapping outside the current subtree
- valueMap.put(propertyName, getSimpleTypeValueMap(data, Arrays.asList(property)));
- }
- } else {
- valueMap.put(propertyName, getStructuralTypeValueMap(value, (EdmStructuralType) property.getType()));
- }
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return valueMap;
- }
-
- private <T> Map<String, Object> getStructuralTypeTypeMap(final T data, final EdmStructuralType type)
- throws ODataException {
- ODataContext context = getContext();
- final int timingHandle = context.startRuntimeMeasurement(getClass().getSimpleName(), "getStructuralTypeTypeMap");
-
- Map<String, Object> typeMap = new HashMap<String, Object>();
- for (final String propertyName : type.getPropertyNames()) {
- final EdmProperty property = (EdmProperty) type.getProperty(propertyName);
- if (property.isSimple()) {
- typeMap.put(propertyName, valueAccess.getPropertyType(data, property));
- } else {
- typeMap.put(propertyName, getStructuralTypeTypeMap(valueAccess.getPropertyValue(data, property),
- (EdmStructuralType) property.getType()));
- }
- }
-
- context.stopRuntimeMeasurement(timingHandle);
-
- return typeMap;
- }
-
- private <T> void setStructuralTypeValuesFromMap(final T data, final EdmStructuralType type,
- final Map<String, Object> valueMap, final boolean merge) throws ODataException {
- ODataContext context = getContext();
- final int timingHandle =
- context.startRuntimeMeasurement(getClass().getSimpleName(), "setStructuralTypeValuesFromMap");
-
- for (final String propertyName : type.getPropertyNames()) {
- final EdmProperty property = (EdmProperty) type.getProperty(propertyName);
- if (type instanceof EdmEntityType && ((EdmEntityType) type).getKeyProperties().contains(property)) {
- Object v = valueAccess.getPropertyValue(data, property);
- if(v != null) {
- continue;
- }
- }
-
- if (!merge || valueMap != null && valueMap.containsKey(propertyName)) {
- final Object value = valueMap == null ? null : valueMap.get(propertyName);
- if (property.isSimple()) {
- valueAccess.setPropertyValue(data, property, value);
- } else {
- @SuppressWarnings("unchecked")
- final Map<String, Object> values = (Map<String, Object>) value;
- setStructuralTypeValuesFromMap(valueAccess.getPropertyValue(data, property),
- (EdmStructuralType) property.getType(), values, merge);
- }
- }
- }
-
- context.stopRuntimeMeasurement(timingHandle);
- }
-
- @Override
- public ODataResponse executeBatch(final BatchHandler handler, final String contentType, final InputStream content)
- throws ODataException {
- ODataResponse batchResponse;
- List<BatchResponsePart> batchResponseParts = new ArrayList<BatchResponsePart>();
- PathInfo pathInfo = getContext().getPathInfo();
- EntityProviderBatchProperties batchProperties = EntityProviderBatchProperties.init().pathInfo(pathInfo).build();
- List<BatchRequestPart> batchParts = EntityProvider.parseBatchRequest(contentType, content, batchProperties);
- for (BatchRequestPart batchPart : batchParts) {
- batchResponseParts.add(handler.handleBatchPart(batchPart));
- }
- batchResponse = EntityProvider.writeBatchResponse(batchResponseParts);
- return batchResponse;
- }
-
- @Override
- public BatchResponsePart executeChangeSet(final BatchHandler handler, final List<ODataRequest> requests)
- throws ODataException {
- List<ODataResponse> responses = new ArrayList<ODataResponse>();
- for (ODataRequest request : requests) {
- ODataResponse response = handler.handleRequest(request);
- if (response.getStatus().getStatusCode() >= HttpStatusCodes.BAD_REQUEST.getStatusCode()) {
- // Rollback
- List<ODataResponse> errorResponses = new ArrayList<ODataResponse>(1);
- errorResponses.add(response);
- return BatchResponsePart.responses(errorResponses).changeSet(false).build();
- }
- responses.add(response);
- }
- return BatchResponsePart.responses(responses).changeSet(true).build();
- }
-}