From b441a524b623e5c2b42ce55a992511a6f6e52ad8 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Fri, 9 Jan 2015 15:08:13 +0100 Subject: [PATCH] [OLINGO-507] (First) Changes for Function/Action support --- .../processor/ComplexCollectionProcessor.java | 14 ++ .../api/processor/ComplexProcessor.java | 16 ++ .../PrimitiveCollectionProcessor.java | 16 ++ .../api/processor/PrimitiveProcessor.java | 15 ++ .../olingo/server/core/ODataHandler.java | 154 ++++++++++++++++-- .../TechnicalPrimitiveComplexProcessor.java | 78 ++++++--- .../tecsvc/provider/ActionProvider.java | 9 +- .../tecsvc/provider/ContainerProvider.java | 8 +- .../tecsvc/provider/SchemaProvider.java | 1 + .../olingo/server/core/ODataHandlerTest.java | 34 ++++ 10 files changed, 304 insertions(+), 41 deletions(-) diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexCollectionProcessor.java index 1fe0b0c99..f6e3e794f 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexCollectionProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexCollectionProcessor.java @@ -63,6 +63,20 @@ public interface ComplexCollectionProcessor extends Processor { ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException; + /** + * Process an action which has as return type a complex-type collection. + * @param request OData request object containing raw HTTP information + * @param response OData response object for collecting response data + * @param uriInfo information of a parsed OData URI + * @param requestFormat content type of body sent with request + * @param responseFormat requested content type after content negotiation + * @throws ODataApplicationException if the service implementation encounters a failure + * @throws DeserializerException if deserialization failed + * @throws SerializerException if serialization failed + */ + void processComplexCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; /** * Deletes complex-type collection from an entity and puts the status into the response. * Deletion for complex-type collection is equal to diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexProcessor.java index 280f42b24..3c7466067 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ComplexProcessor.java @@ -43,6 +43,7 @@ public interface ComplexProcessor extends Processor { */ void readComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException; + /** * Update complex-type instance with send data in the persistence and * puts content, status, and Location into the response. @@ -59,6 +60,21 @@ public interface ComplexProcessor extends Processor { ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException; + /** + * Process an action which has as return type a complex-type. + * @param request OData request object containing raw HTTP information + * @param response OData response object for collecting response data + * @param uriInfo information of a parsed OData URI + * @param requestFormat content type of body sent with request + * @param responseFormat requested content type after content negotiation + * @throws ODataApplicationException if the service implementation encounters a failure + * @throws DeserializerException if deserialization failed + * @throws SerializerException if serialization failed + */ + void processComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; + /** * Deletes complex-type value from an entity and puts the status into the response. * Deletion for complex-type values is equal to diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveCollectionProcessor.java index 07f367855..9770b3b6e 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveCollectionProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveCollectionProcessor.java @@ -75,4 +75,20 @@ public interface PrimitiveCollectionProcessor extends Processor { */ void deletePrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException; + + + /** + * Process an action which has as return type a primitive-type collection. + * @param request OData request object containing raw HTTP information + * @param response OData response object for collecting response data + * @param uriInfo information of a parsed OData URI + * @param requestFormat content type of body sent with request + * @param responseFormat requested content type after content negotiation + * @throws ODataApplicationException if the service implementation encounters a failure + * @throws DeserializerException if deserialization failed + * @throws SerializerException if serialization failed + */ + void processPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; } \ No newline at end of file diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveProcessor.java index e1bf0f03f..86eee10fe 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/PrimitiveProcessor.java @@ -72,4 +72,19 @@ public interface PrimitiveProcessor extends Processor { */ void deletePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException; + + /** + * Process an action which has as return type a primitive-type. + * @param request OData request object containing raw HTTP information + * @param response OData response object for collecting response data + * @param uriInfo information of a parsed OData URI + * @param requestFormat content type of body sent with request + * @param responseFormat requested content type after content negotiation + * @throws ODataApplicationException if the service implementation encounters a failure + * @throws DeserializerException if deserialization failed + * @throws SerializerException if serialization failed + */ + void processPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; } \ No newline at end of file diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java index c36704393..89f6d6396 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandler.java @@ -21,8 +21,13 @@ package org.apache.olingo.server.core; import java.util.LinkedList; import java.util.List; +import org.apache.olingo.commons.api.edm.EdmAction; +import org.apache.olingo.commons.api.edm.EdmActionImport; import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmFunction; +import org.apache.olingo.commons.api.edm.EdmFunctionImport; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edm.EdmReturnType; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; @@ -61,7 +66,9 @@ import org.apache.olingo.server.api.serializer.RepresentationType; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceAction; import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceFunction; import org.apache.olingo.server.api.uri.UriResourceNavigation; import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty; @@ -221,34 +228,43 @@ public class ODataHandler { throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException, SerializerException, DeserializerException { - final HttpMethod method = request.getMethod(); final int lastPathSegmentIndex = uriInfo.getUriResourceParts().size() - 1; final UriResource lastPathSegment = uriInfo.getUriResourceParts().get(lastPathSegmentIndex); switch (lastPathSegment.getKind()) { + case action: + handleActionDispatching(request, response, (UriResourceAction) lastPathSegment); + break; + + case function: + handleFunctionDispatching(request, response, (UriResourceFunction) lastPathSegment); + break; + case entitySet: case navigationProperty: - handleEntityDispatching(request, response, method, (UriResourcePartTyped) lastPathSegment); + handleEntityDispatching(request, response, (UriResourcePartTyped) lastPathSegment); break; case count: - handleCountDispatching(request, response, method, lastPathSegmentIndex); + handleCountDispatching(request, response, lastPathSegmentIndex); break; case primitiveProperty: - handlePrimitivePropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment); + handlePrimitivePropertyDispatching(request, response, false, + ((UriResourceProperty) lastPathSegment).isCollection()); break; case complexProperty: - handleComplexPropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment); + handleComplexPropertyDispatching(request, response, false, + ((UriResourceProperty) lastPathSegment).isCollection()); break; case value: - handleValueDispatching(request, response, method, lastPathSegmentIndex); + handleValueDispatching(request, response, lastPathSegmentIndex); break; case ref: - handleReferenceDispatching(request, response, method, lastPathSegmentIndex); + handleReferenceDispatching(request, response, lastPathSegmentIndex); break; default: @@ -257,10 +273,88 @@ public class ODataHandler { } } + private void handleFunctionDispatching(ODataRequest request, ODataResponse response, + UriResourceFunction uriResourceFunction) + throws ODataHandlerException, SerializerException, ContentNegotiatorException, + ODataApplicationException, DeserializerException { + final HttpMethod method = request.getMethod(); + if(method != HttpMethod.GET) { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + + EdmFunctionImport functionImport = uriResourceFunction.getFunctionImport(); + // could be null for bound functions + if(functionImport == null) { + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + // + + List unboundFunctions = functionImport.getUnboundFunctions(); + if(unboundFunctions == null || unboundFunctions.isEmpty()) { + throw new ODataHandlerException("No unbound function defined for function import", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + EdmReturnType returnType = unboundFunctions.get(0).getReturnType(); + handleOperationDispatching(request, response, uriResourceFunction, false, returnType); + } + + private void handleActionDispatching(ODataRequest request, ODataResponse response, + UriResourceAction uriResourceAction) + throws ODataHandlerException, SerializerException, ContentNegotiatorException, + ODataApplicationException, DeserializerException { + + final HttpMethod method = request.getMethod(); + if(request.getMethod() != HttpMethod.POST) { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + + EdmActionImport functionImport = uriResourceAction.getActionImport(); + // could be null for bound functions + if(functionImport == null) { + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + // + + EdmAction unboundFunctions = functionImport.getUnboundAction(); + if(unboundFunctions == null) { + throw new ODataHandlerException("No unbound function defined for function import", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + EdmReturnType returnType = unboundFunctions.getReturnType(); + handleOperationDispatching(request, response, uriResourceAction, true, returnType); + } + + + private void handleOperationDispatching(ODataRequest request, ODataResponse response, + UriResourcePartTyped uriResource, + boolean isAction, EdmReturnType edmReturnTypeKind) + throws ODataHandlerException, SerializerException, ContentNegotiatorException, + ODataApplicationException, DeserializerException { + + switch (edmReturnTypeKind.getType().getKind()) { + case ENTITY: + handleEntityDispatching(request, response, uriResource); + break; + case PRIMITIVE: + handlePrimitivePropertyDispatching(request, response, isAction, edmReturnTypeKind.isCollection()); + break; + default: + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + } + } + + + private void handleReferenceDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, final int lastPathSegmentIndex) + final int lastPathSegmentIndex) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { + final HttpMethod method = request.getMethod(); if (((UriResourcePartTyped) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).isCollection()) { if (method == HttpMethod.GET) { final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), @@ -297,9 +391,10 @@ public class ODataHandler { } private void handleValueDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, final int lastPathSegmentIndex) + final int lastPathSegmentIndex) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { + final HttpMethod method = request.getMethod(); final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); if (resource instanceof UriResourceProperty) { final RepresentationType valueRepresentationType = @@ -347,12 +442,12 @@ public class ODataHandler { } private void handleComplexPropertyDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, - final UriResourceProperty complexPropertyResource) + final boolean isAction, final boolean isCollection) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { - final RepresentationType complexRepresentationType = complexPropertyResource.isCollection() ? + final HttpMethod method = request.getMethod(); + final RepresentationType complexRepresentationType = isCollection ? RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX; if (method == HttpMethod.GET) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), @@ -376,6 +471,18 @@ public class ODataHandler { selectProcessor(ComplexCollectionProcessor.class) .updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat); } + } else if (method == HttpMethod.POST && isAction) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, complexRepresentationType); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, complexRepresentationType); + if (complexRepresentationType == RepresentationType.COMPLEX) { + selectProcessor(ComplexProcessor.class) + .processComplex(request, response, uriInfo, requestFormat, responseFormat); + } else { + selectProcessor(ComplexCollectionProcessor.class) + .updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat); + } } else if (method == HttpMethod.DELETE) { if (complexRepresentationType == RepresentationType.COMPLEX) { selectProcessor(ComplexProcessor.class).deleteComplex(request, response, uriInfo); @@ -389,10 +496,12 @@ public class ODataHandler { } private void handlePrimitivePropertyDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, final UriResourceProperty propertyResource) + boolean isAction, final boolean isCollection) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { - final RepresentationType representationType = propertyResource.isCollection() ? + + final HttpMethod method = request.getMethod(); + final RepresentationType representationType = isCollection ? RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE; if (method == HttpMethod.GET) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), @@ -421,6 +530,18 @@ public class ODataHandler { } else { selectProcessor(PrimitiveCollectionProcessor.class).deletePrimitiveCollection(request, response, uriInfo); } + } else if (method == HttpMethod.POST && isAction) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, representationType); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, representationType); + if (representationType == RepresentationType.PRIMITIVE) { + selectProcessor(PrimitiveProcessor.class) + .processPrimitive(request, response, uriInfo, requestFormat, responseFormat); + } else { + selectProcessor(PrimitiveCollectionProcessor.class) + .processPrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); + } } else { throw new ODataHandlerException("HTTP method " + method + " is not allowed.", ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); @@ -428,9 +549,10 @@ public class ODataHandler { } private void handleCountDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, final int lastPathSegmentIndex) + final int lastPathSegmentIndex) throws ODataApplicationException, SerializerException, ODataHandlerException { + final HttpMethod method = request.getMethod(); if (method == HttpMethod.GET) { final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) { @@ -450,11 +572,11 @@ public class ODataHandler { } private void handleEntityDispatching(final ODataRequest request, final ODataResponse response, - final HttpMethod method, final UriResourcePartTyped uriResourcePart) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { + final HttpMethod method = request.getMethod(); if (uriResourcePart.isCollection()) { if (method == HttpMethod.GET) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java index d4889d766..a98a9887f 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalPrimitiveComplexProcessor.java @@ -95,6 +95,14 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor deleteProperty(response, uriInfo); } + @Override + public void processPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void readPrimitiveCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType contentType) throws ODataApplicationException, SerializerException { @@ -115,6 +123,14 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor deleteProperty(response, uriInfo); } + @Override + public void processPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType + requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, + SerializerException { + throw new ODataApplicationException("Not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void readComplex(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType contentType) throws ODataApplicationException, SerializerException { @@ -129,6 +145,14 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + @Override + public void processComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType + requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, + SerializerException { + throw new ODataApplicationException("Not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void deleteComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException { @@ -149,6 +173,14 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + @Override + public void processComplexCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType + requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, + SerializerException { + throw new ODataApplicationException("Not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void deleteComplexCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException { @@ -190,28 +222,28 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor helper.buildContextURLSelectList((EdmStructuredType) edmProperty.getType(), expand, select)) .build(); switch (representationType) { - case PRIMITIVE: - response.setContent(serializer.primitive((EdmPrimitiveType) edmProperty.getType(), property, - PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build())); - break; - case COMPLEX: - response.setContent(serializer.complex((EdmComplexType) edmProperty.getType(), property, - ComplexSerializerOptions.with().contextURL(contextURL) - .expand(expand).select(select) - .build())); - break; - case COLLECTION_PRIMITIVE: - response.setContent(serializer.primitiveCollection((EdmPrimitiveType) edmProperty.getType(), property, - PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build())); - break; - case COLLECTION_COMPLEX: - response.setContent(serializer.complexCollection((EdmComplexType) edmProperty.getType(), property, - ComplexSerializerOptions.with().contextURL(contextURL) - .expand(expand).select(select) - .build())); - break; - default: - break; + case PRIMITIVE: + response.setContent(serializer.primitive((EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build())); + break; + case COMPLEX: + response.setContent(serializer.complex((EdmComplexType) edmProperty.getType(), property, + ComplexSerializerOptions.with().contextURL(contextURL) + .expand(expand).select(select) + .build())); + break; + case COLLECTION_PRIMITIVE: + response.setContent(serializer.primitiveCollection((EdmPrimitiveType) edmProperty.getType(), property, + PrimitiveSerializerOptions.with().contextURL(contextURL).facetsFrom(edmProperty).build())); + break; + case COLLECTION_COMPLEX: + response.setContent(serializer.complexCollection((EdmComplexType) edmProperty.getType(), property, + ComplexSerializerOptions.with().contextURL(contextURL) + .expand(expand).select(select) + .build())); + break; + default: + break; } response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, contentType.toContentTypeString()); @@ -239,7 +271,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor } private Property getPropertyData(final UriResourceEntitySet resourceEntitySet, final List path) - throws ODataApplicationException { + throws ODataApplicationException { final Entity entity = dataProvider.read(resourceEntitySet.getEntitySet(), resourceEntitySet.getKeyPredicates()); if (entity == null) { throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java index 729855d76..d204bf495 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ActionProvider.java @@ -46,6 +46,8 @@ public class ActionProvider { new FullQualifiedName(SchemaProvider.NAMESPACE, "BAETTwoKeyNavRTETTwoKeyNav"); // Unbound Actions + public static final FullQualifiedName nameUARTString = new FullQualifiedName(SchemaProvider.NAMESPACE, + "UARTString"); public static final FullQualifiedName nameUARTCompCollParam = new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTCompCollParam"); public static final FullQualifiedName nameUARTCompParam = new FullQualifiedName(SchemaProvider.NAMESPACE, @@ -62,8 +64,13 @@ public class ActionProvider { "UARTPrimCollParam"); public List getActions(final FullQualifiedName actionName) throws ODataException { - if (actionName.equals(nameUARTPrimParam)) { + if (actionName.equals(nameUARTString)) { return Arrays.asList( + new Action().setName(nameUARTString.getName()) + .setReturnType(new ReturnType().setType(PropertyProvider.nameString)) + ); + } else if (actionName.equals(nameUARTPrimParam)) { + return Arrays.asList( new Action().setName("UARTPrimParam") .setParameters(Arrays.asList( new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java index 813bb877e..dfdd4e2c5 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ContainerProvider.java @@ -98,6 +98,7 @@ public class ContainerProvider { // ActionImports List actionImports = new ArrayList(); container.setActionImports(actionImports); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTString")); actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTPrimParam")); actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTPrimCollParam")); actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTCompParam")); @@ -261,7 +262,12 @@ public class ContainerProvider { public ActionImport getActionImport(final FullQualifiedName entityContainer, final String name) throws ODataException { if (entityContainer.equals(nameContainer)) { - if (name.equals("AIRTPrimParam")) { + if (name.equals("AIRTString")) { + return new ActionImport() + .setName("AIRTString") + .setAction(ActionProvider.nameUARTString); + + } else if (name.equals("AIRTPrimParam")) { return new ActionImport() .setName("AIRTPrimParam") .setAction(ActionProvider.nameUARTPrimParam); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java index 3e6386739..480685736 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java @@ -107,6 +107,7 @@ public class SchemaProvider { actions.addAll(prov.getActions(ActionProvider.nameBAESTwoKeyNavRTESTwoKeyNav)); actions.addAll(prov.getActions(ActionProvider.nameBAETBaseTwoKeyNavRTETBaseTwoKeyNav)); actions.addAll(prov.getActions(ActionProvider.nameBAETTwoBaseTwoKeyNavRTETBaseTwoKeyNav)); + actions.addAll(prov.getActions(ActionProvider.nameUARTString)); actions.addAll(prov.getActions(ActionProvider.nameUARTPrimParam)); actions.addAll(prov.getActions(ActionProvider.nameUARTPrimCollParam)); actions.addAll(prov.getActions(ActionProvider.nameUARTCompParam)); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java index c872713c4..b32af8979 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ODataHandlerTest.java @@ -278,6 +278,40 @@ public class ODataHandlerTest { any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class)); } + @Test + public void dispatchFunction() throws Exception { + final String uri = "FICRTCollString()"; + final PrimitiveCollectionProcessor processor = mock(PrimitiveCollectionProcessor.class); + + dispatch(HttpMethod.GET, uri, processor); + verify(processor).readPrimitiveCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + +// dispatch(HttpMethod.GET, uri, processor); +// verify(processor).readEntity( +// any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + dispatchMethodNotAllowed(HttpMethod.POST, uri, processor); + } + + + @Test + public void dispatchAction() throws Exception { + final String uri = "AIRTString"; + + PrimitiveProcessor processor = mock(PrimitiveProcessor.class); + dispatch(HttpMethod.POST, uri, processor); + verify(processor).processPrimitive( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + +// dispatch(HttpMethod.POST, uri, processor); +// verify(processor).readEntity( +// any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + dispatchMethodNotAllowed(HttpMethod.GET, uri, processor); + } + @Test public void dispatchEntity() throws Exception { final String uri = "ESAllPrim(0)";