From 6b0d6d2544fb1c6fb9f85a4e05e7bebfaf3f4847 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Thu, 8 Jan 2015 14:22:19 +0100 Subject: [PATCH 1/5] [OLINGO-507] Split 'handleResourceDispatching' into several smaller methods --- .../olingo/fit/tecsvc/client/BasicITCase.java | 41 ++ .../olingo/server/core/ContentNegotiator.java | 13 + .../core/ContentNegotiatorException.java | 1 + .../olingo/server/core/ODataHandler.java | 585 ++++++++++-------- .../server/core/ODataHandlerException.java | 3 +- .../server-core-exceptions-i18n.properties | 1 + 6 files changed, 375 insertions(+), 269 deletions(-) diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java index 023729c93..f6a5520a1 100644 --- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java +++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java @@ -34,11 +34,14 @@ import java.util.List; import org.apache.olingo.client.api.CommonODataClient; import org.apache.olingo.client.api.communication.ODataClientErrorException; +import org.apache.olingo.client.api.communication.ODataServerErrorException; +import org.apache.olingo.client.api.communication.request.cud.ODataEntityCreateRequest; import org.apache.olingo.client.api.communication.request.retrieve.EdmMetadataRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataServiceDocumentRequest; import org.apache.olingo.client.api.communication.request.retrieve.XMLMetadataRequest; +import org.apache.olingo.client.api.communication.response.ODataEntityCreateResponse; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; import org.apache.olingo.client.api.edm.xml.XMLMetadata; import org.apache.olingo.client.api.edm.xml.v4.Reference; @@ -52,9 +55,11 @@ import org.apache.olingo.commons.api.domain.v4.ODataEntitySet; import org.apache.olingo.commons.api.domain.v4.ODataProperty; import org.apache.olingo.commons.api.domain.v4.ODataValue; import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.commons.core.domain.v4.ODataEntityImpl; import org.apache.olingo.fit.AbstractBaseTestITCase; import org.apache.olingo.fit.tecsvc.TecSvcConst; import org.junit.Test; @@ -188,6 +193,42 @@ public class BasicITCase extends AbstractBaseTestITCase { assertEquals(30112, iterator.next().asPrimitive().toValue()); } + /** + * Actual an create request for an entity will lead to an "501 - Not Implemented" response + * and hence to an ODataServerErrorException + */ + @Test(expected = ODataServerErrorException.class) + public void createEntity() throws IOException { + final ODataEntityRequest request = getClient().getRetrieveRequestFactory() + .getEntityRequest(getClient().newURIBuilder(SERVICE_URI) + .appendEntitySetSegment("ESCollAllPrim").appendKeySegment(1).build()); + assertNotNull(request); + + final ODataRetrieveResponse response = request.execute(); + assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode()); + assertThat(response.getContentType(), containsString(ContentType.APPLICATION_JSON.toContentTypeString())); + + final ODataEntity entity = response.getBody(); + assertNotNull(entity); + + final ODataEntityCreateRequest createRequest = getClient().getCUDRequestFactory() + .getEntityCreateRequest(getClient().newURIBuilder(SERVICE_URI) + .appendEntitySetSegment("ESCollAllPrim").build(), entity); + assertNotNull(createRequest); + ODataEntityCreateResponse createResponse = createRequest.execute(); + + final ODataEntity createdEntity = createResponse.getBody(); + assertNotNull(createdEntity); + final ODataProperty property = createdEntity.getProperty("CollPropertyInt16"); + assertNotNull(property); + assertNotNull(property.getCollectionValue()); + assertEquals(3, property.getCollectionValue().size()); + Iterator iterator = property.getCollectionValue().iterator(); + assertEquals(1000, iterator.next().asPrimitive().toValue()); + assertEquals(2000, iterator.next().asPrimitive().toValue()); + assertEquals(30112, iterator.next().asPrimitive().toValue()); + } + @Override protected CommonODataClient getClient() { ODataClient odata = ODataClientFactory.getV4(); diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java index e84c9c915..f0e3d2de3 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiator.java @@ -151,4 +151,17 @@ public class ContentNegotiator { throw new ContentNegotiatorException("unsupported content type: " + contentType, ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentType.toContentTypeString()); } + + public static boolean isSupported(final ContentType contentType, + final CustomContentTypeSupport customContentTypeSupport, + final RepresentationType representationType) throws ContentNegotiatorException { + + for (final ContentType supportedContentType : + getSupportedContentTypes(customContentTypeSupport, representationType)) { + if (AcceptType.fromContentType(supportedContentType).get(0).matches(contentType)) { + return true; + } + } + return false; + } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java index efd597d19..e2ee86663 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ContentNegotiatorException.java @@ -30,6 +30,7 @@ public class ContentNegotiatorException extends ODataTranslatedException { UNSUPPORTED_CONTENT_TYPES, /** parameter: content type */ UNSUPPORTED_CONTENT_TYPE, + /** no parameter */ NO_CONTENT_TYPE_SUPPORTED, /** parameter: format string */ UNSUPPORTED_FORMAT_OPTION; 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 56293a502..c36704393 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 @@ -22,7 +22,6 @@ import java.util.LinkedList; import java.util.List; import org.apache.olingo.commons.api.edm.EdmEntityType; -import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.format.ContentType; @@ -136,64 +135,70 @@ public class ODataHandler { } private void processInternal(final ODataRequest request, final ODataResponse response) - throws ODataHandlerException, UriParserException, UriValidationException, ContentNegotiatorException, - ODataApplicationException, SerializerException, DeserializerException { + throws ODataHandlerException, UriParserException, UriValidationException, ContentNegotiatorException, + ODataApplicationException, SerializerException, DeserializerException { validateODataVersion(request, response); uriInfo = new Parser().parseUri(request.getRawODataPath(), request.getRawQueryPath(), null, - serviceMetadata.getEdm()); + serviceMetadata.getEdm()); final HttpMethod method = request.getMethod(); new UriValidator().validate(uriInfo, method); switch (uriInfo.getKind()) { - case metadata: - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.METADATA); - selectProcessor(MetadataProcessor.class) - .readMetadata(request, response, uriInfo, requestedContentType); - } else { - throw new ODataHandlerException("HttpMethod " + method + " not allowed for metadata document", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - break; - case service: - if (method == HttpMethod.GET) { - if ("".equals(request.getRawODataPath())) { - selectProcessor(RedirectProcessor.class).redirect(request, response); - } else { + case metadata: + if (method == HttpMethod.GET) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.SERVICE); - - selectProcessor(ServiceDocumentProcessor.class) - .readServiceDocument(request, response, uriInfo, requestedContentType); + request, customContentTypeSupport, RepresentationType.METADATA); + selectProcessor(MetadataProcessor.class) + .readMetadata(request, response, uriInfo, requestedContentType); + } else { + throw new ODataHandlerException("HttpMethod " + method + " not allowed for metadata document", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); } - } else { - throw new ODataHandlerException("HttpMethod " + method + " not allowed for service document", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - break; - case resource: - handleResourceDispatching(request, response); - break; - case batch: - if (method == HttpMethod.POST) { - final BatchProcessor bp = selectProcessor(BatchProcessor.class); - final BatchHandler handler = new BatchHandler(this, bp); - handler.process(request, response, true); - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - break; - default: - throw new ODataHandlerException("not implemented", - ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + break; + + case service: + if (method == HttpMethod.GET) { + if ("".equals(request.getRawODataPath())) { + selectProcessor(RedirectProcessor.class).redirect(request, response); + } else { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.SERVICE); + + selectProcessor(ServiceDocumentProcessor.class) + .readServiceDocument(request, response, uriInfo, requestedContentType); + } + } else { + throw new ODataHandlerException("HttpMethod " + method + " not allowed for service document", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + break; + + case resource: + handleResourceDispatching(request, response); + break; + + case batch: + if (method == HttpMethod.POST) { + final BatchProcessor bp = selectProcessor(BatchProcessor.class); + final BatchHandler handler = new BatchHandler(this, bp); + handler.process(request, response, true); + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + break; + + default: + throw new ODataHandlerException("not implemented", + ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } } - public void handleException(ODataRequest request, ODataResponse response, ODataServerError serverError) { + public void handleException(final ODataRequest request, final ODataResponse response, + final ODataServerError serverError) { + ErrorProcessor exceptionProcessor; try { exceptionProcessor = selectProcessor(ErrorProcessor.class); @@ -204,8 +209,8 @@ public class ODataHandler { ContentType requestedContentType; try { requestedContentType = ContentNegotiator.doContentNegotiation( - uriInfo == null ? null : uriInfo.getFormatOption(), request, customContentTypeSupport, - RepresentationType.ERROR); + uriInfo == null ? null : uriInfo.getFormatOption(), request, customContentTypeSupport, + RepresentationType.ERROR); } catch (final ContentNegotiatorException e) { requestedContentType = ODataFormat.JSON.getContentType(ODataServiceVersion.V40); } @@ -213,274 +218,318 @@ public class ODataHandler { } private void handleResourceDispatching(final ODataRequest request, final ODataResponse response) - throws ODataHandlerException, ContentNegotiatorException, ODataApplicationException, - SerializerException, DeserializerException { + 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 entitySet: - case navigationProperty: - if (((UriResourcePartTyped) lastPathSegment).isCollection()) { - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY); + case entitySet: + case navigationProperty: + handleEntityDispatching(request, response, method, (UriResourcePartTyped) lastPathSegment); + break; - selectProcessor(EntityCollectionProcessor.class) - .readEntityCollection(request, response, uriInfo, requestedContentType); - } else if (method == HttpMethod.POST) { - if (isMedia(lastPathSegment)) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.ENTITY); - selectProcessor(MediaEntityProcessor.class) - .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat); - } else { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.ENTITY); - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.ENTITY); - selectProcessor(EntityProcessor.class) - .createEntity(request, response, uriInfo, requestFormat, responseFormat); - } - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - } else { - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.ENTITY); + case count: + handleCountDispatching(request, response, method, lastPathSegmentIndex); + break; - selectProcessor(EntityProcessor.class) - .readEntity(request, response, uriInfo, requestedContentType); - } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.ENTITY); - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.ENTITY); - selectProcessor(EntityProcessor.class) - .updateEntity(request, response, uriInfo, requestFormat, responseFormat); - } else if (method == HttpMethod.DELETE) { - selectProcessor(isMedia(lastPathSegment) ? MediaEntityProcessor.class : EntityProcessor.class) - .deleteEntity(request, response, uriInfo); - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - } - break; + case primitiveProperty: + handlePrimitivePropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment); + break; - case count: + case complexProperty: + handleComplexPropertyDispatching(request, response, method, (UriResourceProperty) lastPathSegment); + break; + + case value: + handleValueDispatching(request, response, method, lastPathSegmentIndex); + break; + + case ref: + handleReferenceDispatching(request, response, method, lastPathSegmentIndex); + 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) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { + if (((UriResourcePartTyped) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).isCollection()) { if (method == HttpMethod.GET) { - final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); - if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) { - selectProcessor(CountEntityCollectionProcessor.class) - .countEntityCollection(request, response, uriInfo); - } else if (resource instanceof UriResourcePrimitiveProperty) { - selectProcessor(CountPrimitiveCollectionProcessor.class) - .countPrimitiveCollection(request, response, uriInfo); - } else { - selectProcessor(CountComplexCollectionProcessor.class) - .countComplexCollection(request, response, uriInfo); - } - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - break; - - case primitiveProperty: - final UriResourceProperty propertyResource = (UriResourceProperty) lastPathSegment; - final RepresentationType representationType = propertyResource.isCollection() ? - RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE; - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, representationType); - if (representationType == RepresentationType.PRIMITIVE) { - selectProcessor(PrimitiveProcessor.class) - .readPrimitive(request, response, uriInfo, requestedContentType); - } else { - selectProcessor(PrimitiveCollectionProcessor.class) - .readPrimitiveCollection(request, response, uriInfo, requestedContentType); - } - } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, representationType); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, representationType); - if (representationType == RepresentationType.PRIMITIVE) { - selectProcessor(PrimitiveProcessor.class) - .updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); - } else { - selectProcessor(PrimitiveCollectionProcessor.class) - .updatePrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); - } - } else if (method == HttpMethod.DELETE) { - if (representationType == RepresentationType.PRIMITIVE) { - selectProcessor(PrimitiveProcessor.class) - .deletePrimitive(request, response, uriInfo); - } else { - selectProcessor(PrimitiveCollectionProcessor.class) - .deletePrimitiveCollection(request, response, uriInfo); - } + request, customContentTypeSupport, RepresentationType.COLLECTION_REFERENCE); + selectProcessor(ReferenceCollectionProcessor.class) + .readReferenceCollection(request, response, uriInfo, responseFormat); + } else if (method == HttpMethod.POST) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE); + selectProcessor(ReferenceProcessor.class) + .createReference(request, response, uriInfo, requestFormat); } else { throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); } - break; - - case complexProperty: - final UriResourceProperty complexPropertyResource = (UriResourceProperty) lastPathSegment; - final RepresentationType complexRepresentationType = complexPropertyResource.isCollection() ? - RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX; + } else { if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, complexRepresentationType); - if (complexRepresentationType == RepresentationType.COMPLEX) { - selectProcessor(ComplexProcessor.class) - .readComplex(request, response, uriInfo, requestedContentType); - } else { - selectProcessor(ComplexCollectionProcessor.class) - .readComplexCollection(request, response, uriInfo, requestedContentType); - } + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.REFERENCE); + selectProcessor(ReferenceProcessor.class).readReference(request, response, uriInfo, responseFormat); } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, complexRepresentationType); - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, complexRepresentationType); - if (complexRepresentationType == RepresentationType.COMPLEX) { - selectProcessor(ComplexProcessor.class) - .updateComplex(request, response, uriInfo, requestFormat, responseFormat); - } else { - selectProcessor(ComplexCollectionProcessor.class) - .updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat); - } + checkContentTypeSupport(requestFormat, RepresentationType.REFERENCE); + selectProcessor(ReferenceProcessor.class) + .updateReference(request, response, uriInfo, requestFormat); } else if (method == HttpMethod.DELETE) { - if (complexRepresentationType == RepresentationType.COMPLEX) { - selectProcessor(ComplexProcessor.class) - .deleteComplex(request, response, uriInfo); - } else { - selectProcessor(ComplexCollectionProcessor.class) - .deleteComplexCollection(request, response, uriInfo); - } + selectProcessor(ReferenceProcessor.class) + .deleteReference(request, response, uriInfo); } else { throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); } - break; + } + } - case value: - final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); - if (resource instanceof UriResourceProperty) { - final RepresentationType valueRepresentationType = - (EdmPrimitiveType) ((UriResourceProperty) resource).getType() == - EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ? - RepresentationType.BINARY : RepresentationType.VALUE; - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, valueRepresentationType); + private void handleValueDispatching(final ODataRequest request, final ODataResponse response, + final HttpMethod method, final int lastPathSegmentIndex) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { + final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); + if (resource instanceof UriResourceProperty) { + final RepresentationType valueRepresentationType = + ((UriResourceProperty) resource).getType() == + EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ? + RepresentationType.BINARY : RepresentationType.VALUE; + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, valueRepresentationType); - selectProcessor(PrimitiveValueProcessor.class) - .readPrimitiveValue(request, response, uriInfo, requestedContentType); - } else if (method == HttpMethod.PUT) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, valueRepresentationType); - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, valueRepresentationType); - selectProcessor(PrimitiveValueProcessor.class) - .updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); - } else if (method == HttpMethod.DELETE) { - selectProcessor(PrimitiveValueProcessor.class) - .deletePrimitive(request, response, uriInfo); - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } + selectProcessor(PrimitiveValueProcessor.class) + .readPrimitiveValue(request, response, uriInfo, requestedContentType); + } else if (method == HttpMethod.PUT) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, valueRepresentationType); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, valueRepresentationType); + selectProcessor(PrimitiveValueProcessor.class) + .updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); + } else if (method == HttpMethod.DELETE) { + selectProcessor(PrimitiveValueProcessor.class).deletePrimitive(request, response, uriInfo); } else { - if (method == HttpMethod.GET) { - final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.MEDIA); - selectProcessor(MediaEntityProcessor.class) - .readMediaEntity(request, response, uriInfo, requestedContentType); - } else if (method == HttpMethod.PUT) { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } else { + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.MEDIA); + selectProcessor(MediaEntityProcessor.class) + .readMediaEntity(request, response, uriInfo, requestedContentType); + } else if (method == HttpMethod.PUT) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); + selectProcessor(MediaEntityProcessor.class) + .updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat); + } else if (method == HttpMethod.DELETE) { + selectProcessor(MediaEntityProcessor.class).deleteEntity(request, response, uriInfo); + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } + } + + private void handleComplexPropertyDispatching(final ODataRequest request, final ODataResponse response, + final HttpMethod method, + final UriResourceProperty complexPropertyResource) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { + + final RepresentationType complexRepresentationType = complexPropertyResource.isCollection() ? + RepresentationType.COLLECTION_COMPLEX : RepresentationType.COMPLEX; + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, complexRepresentationType); + if (complexRepresentationType == RepresentationType.COMPLEX) { + selectProcessor(ComplexProcessor.class) + .readComplex(request, response, uriInfo, requestedContentType); + } else { + selectProcessor(ComplexCollectionProcessor.class) + .readComplexCollection(request, response, uriInfo, requestedContentType); + } + } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { + 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) + .updateComplex(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); + } else { + selectProcessor(ComplexCollectionProcessor.class).deleteComplexCollection(request, response, uriInfo); + } + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } + + private void handlePrimitivePropertyDispatching(final ODataRequest request, final ODataResponse response, + final HttpMethod method, final UriResourceProperty propertyResource) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { + final RepresentationType representationType = propertyResource.isCollection() ? + RepresentationType.COLLECTION_PRIMITIVE : RepresentationType.PRIMITIVE; + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, representationType); + if (representationType == RepresentationType.PRIMITIVE) { + selectProcessor(PrimitiveProcessor.class).readPrimitive(request, response, uriInfo, requestedContentType); + } else { + selectProcessor(PrimitiveCollectionProcessor.class) + .readPrimitiveCollection(request, response, uriInfo, requestedContentType); + } + } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { + 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) + .updatePrimitive(request, response, uriInfo, requestFormat, responseFormat); + } else { + selectProcessor(PrimitiveCollectionProcessor.class) + .updatePrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); + } + } else if (method == HttpMethod.DELETE) { + if (representationType == RepresentationType.PRIMITIVE) { + selectProcessor(PrimitiveProcessor.class).deletePrimitive(request, response, uriInfo); + } else { + selectProcessor(PrimitiveCollectionProcessor.class).deletePrimitiveCollection(request, response, uriInfo); + } + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } + + private void handleCountDispatching(final ODataRequest request, final ODataResponse response, + final HttpMethod method, final int lastPathSegmentIndex) + throws ODataApplicationException, SerializerException, ODataHandlerException { + + if (method == HttpMethod.GET) { + final UriResource resource = uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1); + if (resource instanceof UriResourceEntitySet || resource instanceof UriResourceNavigation) { + selectProcessor(CountEntityCollectionProcessor.class) + .countEntityCollection(request, response, uriInfo); + } else if (resource instanceof UriResourcePrimitiveProperty) { + selectProcessor(CountPrimitiveCollectionProcessor.class) + .countPrimitiveCollection(request, response, uriInfo); + } else { + selectProcessor(CountComplexCollectionProcessor.class) + .countComplexCollection(request, response, uriInfo); + } + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } + + private void handleEntityDispatching(final ODataRequest request, final ODataResponse response, + final HttpMethod method, + final UriResourcePartTyped uriResourcePart) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { + + if (uriResourcePart.isCollection()) { + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY); + + selectProcessor(EntityCollectionProcessor.class) + .readEntityCollection(request, response, uriInfo, requestedContentType); + } else if (method == HttpMethod.POST) { + if (isMedia(uriResourcePart)) { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); selectProcessor(MediaEntityProcessor.class) - .updateMediaEntity(request, response, uriInfo, requestFormat, responseFormat); - } else if (method == HttpMethod.DELETE) { - selectProcessor(MediaEntityProcessor.class) - .deleteEntity(request, response, uriInfo); + .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat); } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } - } - break; - - case ref: - if (((UriResourcePartTyped) uriInfo.getUriResourceParts().get(lastPathSegmentIndex - 1)).isCollection()) { - if (method == HttpMethod.GET) { - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.COLLECTION_REFERENCE); - selectProcessor(ReferenceCollectionProcessor.class) - .readReferenceCollection(request, response, uriInfo, responseFormat); - } else if (method == HttpMethod.POST) { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.REFERENCE); - selectProcessor(ReferenceProcessor.class) - .createReference(request, response, uriInfo, requestFormat); - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); + selectProcessor(EntityProcessor.class) + .createEntity(request, response, uriInfo, requestFormat, responseFormat); } } else { - if (method == HttpMethod.GET) { - final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), - request, customContentTypeSupport, RepresentationType.REFERENCE); - selectProcessor(ReferenceProcessor.class) - .readReference(request, response, uriInfo, responseFormat); - } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); - ContentNegotiator.checkSupport(requestFormat, customContentTypeSupport, RepresentationType.REFERENCE); - selectProcessor(ReferenceProcessor.class) - .updateReference(request, response, uriInfo, requestFormat); - } else if (method == HttpMethod.DELETE) { - selectProcessor(ReferenceProcessor.class) - .deleteReference(request, response, uriInfo); - } else { - throw new ODataHandlerException("HTTP method " + method + " is not allowed.", - ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); - } + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); } - break; + } else { + if (method == HttpMethod.GET) { + final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); - default: - throw new ODataHandlerException("not implemented", - ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); + selectProcessor(EntityProcessor.class).readEntity(request, response, uriInfo, requestedContentType); + } else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); + selectProcessor(EntityProcessor.class).updateEntity(request, response, uriInfo, requestFormat, responseFormat); + } else if (method == HttpMethod.DELETE) { + selectProcessor(isMedia(uriResourcePart) ? MediaEntityProcessor.class : EntityProcessor.class) + .deleteEntity(request, response, uriInfo); + } else { + throw new ODataHandlerException("HTTP method " + method + " is not allowed.", + ODataHandlerException.MessageKeys.HTTP_METHOD_NOT_ALLOWED, method.toString()); + } + } + } + + private void checkContentTypeSupport(ContentType requestFormat, RepresentationType representationType) + throws ODataHandlerException, ContentNegotiatorException { + if (!ContentNegotiator.isSupported(requestFormat, customContentTypeSupport, representationType)) { + final String contentTypeString = requestFormat.toContentTypeString(); + throw new ODataHandlerException("ContentType " + contentTypeString + " is not supported.", + ODataHandlerException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentTypeString); } } private void validateODataVersion(final ODataRequest request, final ODataResponse response) - throws ODataHandlerException { + throws ODataHandlerException { final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION); response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString()); if (maxVersion != null) { if (ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) { throw new ODataHandlerException("ODataVersion not supported: " + maxVersion, - ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED, maxVersion); + ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED, maxVersion); } } } private boolean isMedia(final UriResource pathSegment) { return pathSegment instanceof UriResourceEntitySet - && ((UriResourceEntitySet) pathSegment).getEntityType().hasStream() - || pathSegment instanceof UriResourceNavigation - && ((EdmEntityType) ((UriResourceNavigation) pathSegment).getType()).hasStream(); + && ((UriResourceEntitySet) pathSegment).getEntityType().hasStream() + || pathSegment instanceof UriResourceNavigation + && ((EdmEntityType) ((UriResourceNavigation) pathSegment).getType()).hasStream(); } private T selectProcessor(final Class cls) throws ODataHandlerException { @@ -491,7 +540,7 @@ public class ODataHandler { } } throw new ODataHandlerException("Processor: " + cls.getSimpleName() + " not registered.", - ODataHandlerException.MessageKeys.PROCESSOR_NOT_IMPLEMENTED, cls.getSimpleName()); + ODataHandlerException.MessageKeys.PROCESSOR_NOT_IMPLEMENTED, cls.getSimpleName()); } public void register(final Processor processor) { diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java index cc4d66272..8ebbc26c2 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/ODataHandlerException.java @@ -29,7 +29,8 @@ public class ODataHandlerException extends ODataTranslatedException { /** parameter: HTTP method */ INVALID_HTTP_METHOD, /** parameter: HTTP method */ HTTP_METHOD_NOT_ALLOWED, /** parameter: processor interface */ PROCESSOR_NOT_IMPLEMENTED, - FUNCTIONALITY_NOT_IMPLEMENTED, + /** no parameter */ FUNCTIONALITY_NOT_IMPLEMENTED, + /** parameter: content type */ UNSUPPORTED_CONTENT_TYPE, /** parameter: version */ ODATA_VERSION_NOT_SUPPORTED; @Override diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties index c61619d98..034a6bde5 100644 --- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties +++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties @@ -24,6 +24,7 @@ ODataHandlerException.HTTP_METHOD_NOT_ALLOWED=HTTP method '%1$s' not allowed for ODataHandlerException.PROCESSOR_NOT_IMPLEMENTED=No processor for interface '%1$s' registered. ODataHandlerException.FUNCTIONALITY_NOT_IMPLEMENTED=The requested functionality has not been implemented (yet). ODataHandlerException.ODATA_VERSION_NOT_SUPPORTED=OData version '%1$s' is not supported. +ODataHandlerException.UNSUPPORTED_CONTENT_TYPE=The content type '%1$s' is not supported for this request. UriParserSyntaxException.MUST_BE_LAST_SEGMENT=The segment '%1$s' must be the last segment. UriParserSyntaxException.UNKNOWN_SYSTEM_QUERY_OPTION=The system query option '%1$s' is not defined. From b441a524b623e5c2b42ce55a992511a6f6e52ad8 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Fri, 9 Jan 2015 15:08:13 +0100 Subject: [PATCH 2/5] [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)"; From 186d67241da3501fe3577eca3ac42d025a48ff5a Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Mon, 12 Jan 2015 10:15:06 +0100 Subject: [PATCH 3/5] [OLINGO-507] Changes and test for FunctionImports support --- .../olingo/server/core/ODataHandler.java | 54 ++++++++++--------- .../olingo/server/core/ODataHandlerTest.java | 39 ++++++++++---- .../sample/processor/CarsProcessor.java | 18 +++++++ 3 files changed, 78 insertions(+), 33 deletions(-) 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 89f6d6396..dc7864780 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 @@ -273,8 +273,8 @@ public class ODataHandler { } } - private void handleFunctionDispatching(ODataRequest request, ODataResponse response, - UriResourceFunction uriResourceFunction) + private void handleFunctionDispatching(final ODataRequest request, final ODataResponse response, + final UriResourceFunction uriResourceFunction) throws ODataHandlerException, SerializerException, ContentNegotiatorException, ODataApplicationException, DeserializerException { final HttpMethod method = request.getMethod(); @@ -286,10 +286,9 @@ public class ODataHandler { EdmFunctionImport functionImport = uriResourceFunction.getFunctionImport(); // could be null for bound functions if(functionImport == null) { - throw new ODataHandlerException("not implemented", + throw new ODataHandlerException("Bound functions are not implemented yet", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } - // List unboundFunctions = functionImport.getUnboundFunctions(); if(unboundFunctions == null || unboundFunctions.isEmpty()) { @@ -297,11 +296,11 @@ public class ODataHandler { ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } EdmReturnType returnType = unboundFunctions.get(0).getReturnType(); - handleOperationDispatching(request, response, uriResourceFunction, false, returnType); + handleOperationDispatching(request, response, false, returnType); } - private void handleActionDispatching(ODataRequest request, ODataResponse response, - UriResourceAction uriResourceAction) + private void handleActionDispatching(final ODataRequest request, final ODataResponse response, + final UriResourceAction uriResourceAction) throws ODataHandlerException, SerializerException, ContentNegotiatorException, ODataApplicationException, DeserializerException { @@ -311,37 +310,38 @@ public class ODataHandler { 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", + EdmActionImport actionImport = uriResourceAction.getActionImport(); + // could be null for bound actions + if(actionImport == null) { + throw new ODataHandlerException("Bound actions are not implemented yet", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); } - // - EdmAction unboundFunctions = functionImport.getUnboundAction(); - if(unboundFunctions == null) { + EdmAction unboundActions = actionImport.getUnboundAction(); + if(unboundActions == 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); + EdmReturnType returnType = unboundActions.getReturnType(); + handleOperationDispatching(request, response, true, returnType); } - private void handleOperationDispatching(ODataRequest request, ODataResponse response, - UriResourcePartTyped uriResource, - boolean isAction, EdmReturnType edmReturnTypeKind) + private void handleOperationDispatching(final ODataRequest request, final ODataResponse response, + final boolean isAction, final EdmReturnType edmReturnTypeKind) throws ODataHandlerException, SerializerException, ContentNegotiatorException, ODataApplicationException, DeserializerException { switch (edmReturnTypeKind.getType().getKind()) { case ENTITY: - handleEntityDispatching(request, response, uriResource); + handleEntityDispatching(request, response, edmReturnTypeKind.isCollection(), false); break; case PRIMITIVE: handlePrimitivePropertyDispatching(request, response, isAction, edmReturnTypeKind.isCollection()); break; + case COMPLEX: + handleComplexPropertyDispatching(request, response, isAction, edmReturnTypeKind.isCollection()); + break; default: throw new ODataHandlerException("not implemented", ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED); @@ -349,7 +349,6 @@ public class ODataHandler { } - private void handleReferenceDispatching(final ODataRequest request, final ODataResponse response, final int lastPathSegmentIndex) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, @@ -575,9 +574,16 @@ public class ODataHandler { final UriResourcePartTyped uriResourcePart) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { + handleEntityDispatching(request, response, uriResourcePart.isCollection(), isMedia(uriResourcePart)); + } + + private void handleEntityDispatching(final ODataRequest request, final ODataResponse response, + final boolean isCollection, final boolean isMedia) + throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, + DeserializerException { final HttpMethod method = request.getMethod(); - if (uriResourcePart.isCollection()) { + if (isCollection) { if (method == HttpMethod.GET) { final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.COLLECTION_ENTITY); @@ -585,7 +591,7 @@ public class ODataHandler { selectProcessor(EntityCollectionProcessor.class) .readEntityCollection(request, response, uriInfo, requestedContentType); } else if (method == HttpMethod.POST) { - if (isMedia(uriResourcePart)) { + if (isMedia) { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); @@ -616,7 +622,7 @@ public class ODataHandler { request, customContentTypeSupport, RepresentationType.ENTITY); selectProcessor(EntityProcessor.class).updateEntity(request, response, uriInfo, requestFormat, responseFormat); } else if (method == HttpMethod.DELETE) { - selectProcessor(isMedia(uriResourcePart) ? MediaEntityProcessor.class : EntityProcessor.class) + selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class) .deleteEntity(request, response, uriInfo); } else { throw new ODataHandlerException("HTTP method " + method + " is not allowed.", 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 b32af8979..03e521333 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 @@ -280,18 +280,39 @@ public class ODataHandlerTest { @Test public void dispatchFunction() throws Exception { - final String uri = "FICRTCollString()"; - final PrimitiveCollectionProcessor processor = mock(PrimitiveCollectionProcessor.class); - - dispatch(HttpMethod.GET, uri, processor); - verify(processor).readPrimitiveCollection( + EntityProcessor entityProcessor = mock(EntityProcessor.class); + dispatch(HttpMethod.GET, "FICRTETKeyNav()", entityProcessor); + verify(entityProcessor).readEntity( 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)); + EntityCollectionProcessor entityCollectionProcessor = mock(EntityCollectionProcessor.class); + dispatch(HttpMethod.GET, "FICRTESTwoKeyNavParam(ParameterInt16=123)", entityCollectionProcessor); + verify(entityCollectionProcessor).readEntityCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); - dispatchMethodNotAllowed(HttpMethod.POST, uri, processor); + PrimitiveProcessor primitiveProcessor = mock(PrimitiveProcessor.class); + dispatch(HttpMethod.GET, "FICRTString()", primitiveProcessor); + verify(primitiveProcessor).readPrimitive( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + PrimitiveCollectionProcessor primitiveCollectionProcessor = mock(PrimitiveCollectionProcessor.class); + dispatch(HttpMethod.GET, "FICRTCollString()", primitiveCollectionProcessor); + verify(primitiveCollectionProcessor).readPrimitiveCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + ComplexProcessor complexProcessor = mock(ComplexProcessor.class); + dispatch(HttpMethod.GET, "FICRTCTTwoPrim()", complexProcessor); + verify(complexProcessor).readComplex( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + ComplexCollectionProcessor complexCollectionProcessor = mock(ComplexCollectionProcessor.class); + dispatch(HttpMethod.GET, "FICRTCollCTTwoPrim()", complexCollectionProcessor); + verify(complexCollectionProcessor).readComplexCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class)); + + dispatchMethodNotAllowed(HttpMethod.POST, "FICRTCollString()", mock(Processor.class)); + dispatchMethodNotAllowed(HttpMethod.PUT, "FICRTCollString()", mock(Processor.class)); + dispatchMethodNotAllowed(HttpMethod.DELETE, "FICRTCollString()", mock(Processor.class)); } diff --git a/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java b/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java index 3f15483a6..f3747dcbd 100644 --- a/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java +++ b/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java @@ -336,6 +336,15 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + @Override + public void processPrimitive(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, final ContentType requestFormat, + final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process Primitive property update is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void updateComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, @@ -345,6 +354,15 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + @Override + public void processComplex(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, final ContentType requestFormat, + final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process Complex property update is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void deleteComplex(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException { From 2f6b35ff5980bfb36a299cc2ae4891e43d5f4853 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Mon, 12 Jan 2015 14:48:14 +0100 Subject: [PATCH 4/5] [OLINGO-507] Added methods and tests for ActionImports support --- .../processor/EntityCollectionProcessor.java | 16 +++ .../server/api/processor/EntityProcessor.java | 15 +++ .../olingo/server/core/ODataHandler.java | 23 +++- .../processor/TechnicalEntityProcessor.java | 18 +++ .../tecsvc/provider/ActionProvider.java | 121 +++++++++--------- .../tecsvc/provider/ContainerProvider.java | 72 ++++++----- .../tecsvc/provider/SchemaProvider.java | 13 +- .../olingo/server/core/ODataHandlerTest.java | 57 +++++++-- .../serializer/xml/MetadataDocumentTest.java | 6 +- .../server/core/uri/UriResourceImplTest.java | 8 +- .../core/uri/antlr/TestFullResourcePath.java | 11 +- .../core/uri/antlr/TestUriParserImpl.java | 38 +++--- .../expression/ExpressionTest.java | 8 +- .../core/uri/validator/UriValidatorTest.java | 7 +- .../sample/processor/CarsProcessor.java | 24 +++- 15 files changed, 289 insertions(+), 148 deletions(-) diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java index d1c927cb5..91fb94ce7 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java @@ -22,6 +22,7 @@ import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; import org.apache.olingo.server.api.serializer.SerializerException; import org.apache.olingo.server.api.uri.UriInfo; @@ -41,4 +42,19 @@ public interface EntityCollectionProcessor extends Processor { */ void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException; + + /** + * Process an action which has as return type a collection of entities. + * @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 org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws SerializerException if serialization failed + */ + void processEntityCollection(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/EntityProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java index 6e4610b4b..06d88f349 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java @@ -81,4 +81,19 @@ public interface EntityProcessor extends Processor { * @throws ODataApplicationException if the service implementation encounters a failure */ void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException; + + /** + * Process an action which has as return type an entity. + * @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 processEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; } 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 dc7864780..d14717c4f 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 @@ -334,7 +334,7 @@ public class ODataHandler { switch (edmReturnTypeKind.getType().getKind()) { case ENTITY: - handleEntityDispatching(request, response, edmReturnTypeKind.isCollection(), false); + handleEntityDispatching(request, response, edmReturnTypeKind.isCollection(), false, isAction); break; case PRIMITIVE: handlePrimitivePropertyDispatching(request, response, isAction, edmReturnTypeKind.isCollection()); @@ -480,7 +480,7 @@ public class ODataHandler { .processComplex(request, response, uriInfo, requestFormat, responseFormat); } else { selectProcessor(ComplexCollectionProcessor.class) - .updateComplexCollection(request, response, uriInfo, requestFormat, responseFormat); + .processComplexCollection(request, response, uriInfo, requestFormat, responseFormat); } } else if (method == HttpMethod.DELETE) { if (complexRepresentationType == RepresentationType.COMPLEX) { @@ -574,11 +574,11 @@ public class ODataHandler { final UriResourcePartTyped uriResourcePart) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { - handleEntityDispatching(request, response, uriResourcePart.isCollection(), isMedia(uriResourcePart)); + handleEntityDispatching(request, response, uriResourcePart.isCollection(), isMedia(uriResourcePart), false); } private void handleEntityDispatching(final ODataRequest request, final ODataResponse response, - final boolean isCollection, final boolean isMedia) + final boolean isCollection, final boolean isMedia, boolean isAction) throws ContentNegotiatorException, ODataApplicationException, SerializerException, ODataHandlerException, DeserializerException { @@ -591,14 +591,19 @@ public class ODataHandler { selectProcessor(EntityCollectionProcessor.class) .readEntityCollection(request, response, uriInfo, requestedContentType); } else if (method == HttpMethod.POST) { - if (isMedia) { final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + if (isMedia) { final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); selectProcessor(MediaEntityProcessor.class) .createMediaEntity(request, response, uriInfo, requestFormat, responseFormat); + } else if(isAction) { + checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); + selectProcessor(EntityCollectionProcessor.class) + .processEntityCollection(request, response, uriInfo, requestFormat, responseFormat); } else { - final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); @@ -621,6 +626,12 @@ public class ODataHandler { final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); selectProcessor(EntityProcessor.class).updateEntity(request, response, uriInfo, requestFormat, responseFormat); + } else if (method == HttpMethod.POST && isAction) { + final ContentType requestFormat = ContentType.parse(request.getHeader(HttpHeader.CONTENT_TYPE)); + checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); + final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), + request, customContentTypeSupport, RepresentationType.ENTITY); + selectProcessor(EntityProcessor.class).processEntity(request, response, uriInfo, requestFormat, responseFormat); } else if (method == HttpMethod.DELETE) { selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class) .deleteEntity(request, response, uriInfo); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index b1f3ba476..e5bd0ff76 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -89,6 +89,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } } + @Override + public void processEntityCollection(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, + final ContentType requestFormat, final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process entity collection is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void countEntityCollection(final ODataRequest request, ODataResponse response, final UriInfo uriInfo) throws ODataApplicationException, SerializerException { @@ -247,6 +256,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } } + @Override + public void processEntity(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, final ContentType requestFormat, + final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process entity is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + private void blockNavigation(final UriInfo uriInfo) throws ODataApplicationException { final List parts = uriInfo.asUriInfoResource().getUriResourceParts(); if (parts.size() > 2 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 d204bf495..5ff2db52d 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 @@ -21,6 +21,7 @@ package org.apache.olingo.server.tecsvc.provider; import org.apache.olingo.commons.api.ODataException; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.server.api.edm.provider.Action; +import org.apache.olingo.server.api.edm.provider.ComplexType; import org.apache.olingo.server.api.edm.provider.Parameter; import org.apache.olingo.server.api.edm.provider.ReturnType; @@ -48,84 +49,90 @@ public class ActionProvider { // 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, - "UARTCompParam"); - public static final FullQualifiedName nameUARTESParam = - new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTESParam"); + public static final FullQualifiedName nameUARTCollStringTwoParam = new FullQualifiedName(SchemaProvider.NAMESPACE, + "UARTCollStringTwoParam"); + public static final FullQualifiedName nameUARTCollCTTwoPrimParam = new FullQualifiedName(SchemaProvider.NAMESPACE, + "UARTCollCTTwoPrimParam"); + public static final FullQualifiedName nameUARTCTTwoPrimParam = new FullQualifiedName(SchemaProvider.NAMESPACE, + "UARTCTTwoPrimParam"); + public static final FullQualifiedName nameUARTETTwoKeyTwoPrimParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTETTwoKeyTwoPrimParam"); + public static final FullQualifiedName nameUARTCollETKeyNavParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTCollETKeyNavParam"); + public static final FullQualifiedName nameUARTETAllPrimParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTETAllPrimParam"); + public static final FullQualifiedName nameUARTCollETAllPrimParam = + new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTCollETAllPrimParam"); - public static final FullQualifiedName nameUARTETParam = - new FullQualifiedName(SchemaProvider.NAMESPACE, "UARTETParam"); - - public static final FullQualifiedName nameUARTPrimParam = new FullQualifiedName(SchemaProvider.NAMESPACE, - "UARTPrimParam"); - public static final FullQualifiedName nameUARTPrimCollParam = new FullQualifiedName(SchemaProvider.NAMESPACE, - "UARTPrimCollParam"); public List getActions(final FullQualifiedName actionName) throws ODataException { if (actionName.equals(nameUARTString)) { return Arrays.asList( new Action().setName(nameUARTString.getName()) - .setReturnType(new ReturnType().setType(PropertyProvider.nameString)) + .setReturnType(new ReturnType().setType(PropertyProvider.nameString)) ); - } else if (actionName.equals(nameUARTPrimParam)) { + } else if (actionName.equals(nameUARTCollStringTwoParam)) { return Arrays.asList( - new Action().setName("UARTPrimParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + new Action().setName(nameUARTCollStringTwoParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + .setReturnType(new ReturnType().setType(PropertyProvider.nameString).setCollection(true)) + ); - .setReturnType(new ReturnType().setType(PropertyProvider.nameString)) - ); - - } else if (actionName.equals(nameUARTPrimCollParam)) { + } else if (actionName.equals(nameUARTCTTwoPrimParam)) { return Arrays.asList( - new Action().setName("UARTPrimCollParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + new Action().setName(nameUARTCTTwoPrimParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + .setReturnType( + new ReturnType().setType(ComplexTypeProvider.nameCTTwoPrim)) + ); - .setReturnType( - new ReturnType().setType(PropertyProvider.nameString).setCollection(true)) - ); - - } else if (actionName.equals(nameUARTCompParam)) { + } else if (actionName.equals(nameUARTCollCTTwoPrimParam)) { return Arrays.asList( - new Action().setName("UARTCompParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + new Action().setName(nameUARTCollCTTwoPrimParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + .setReturnType( + new ReturnType().setType(ComplexTypeProvider.nameCTTwoPrim).setCollection(true)) + ); - .setReturnType( - new ReturnType().setType(ComplexTypeProvider.nameCTTwoPrim)) - ); - - } else if (actionName.equals(nameUARTCompCollParam)) { + } else if (actionName.equals(nameUARTETTwoKeyTwoPrimParam)) { return Arrays.asList( - new Action().setName("UARTCompCollParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + new Action().setName(nameUARTETTwoKeyTwoPrimParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + .setReturnType( + new ReturnType().setType(EntityTypeProvider.nameETTwoKeyTwoPrim)) + ); - .setReturnType( - new ReturnType().setType(ComplexTypeProvider.nameCTTwoPrim).setCollection(true)) - ); - - } else if (actionName.equals(nameUARTETParam)) { + } else if (actionName.equals(nameUARTCollETKeyNavParam)) { return Arrays.asList( - new Action().setName("UARTETParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) - .setReturnType( - new ReturnType().setType(EntityTypeProvider.nameETTwoKeyTwoPrim)) + new Action().setName(nameUARTCollETKeyNavParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) + .setReturnType( + new ReturnType().setType(EntityTypeProvider.nameETKeyNav).setCollection(true)) ); - } else if (actionName.equals(nameUARTESParam)) { + } else if (actionName.equals(nameUARTETAllPrimParam)) { return Arrays.asList( - new Action().setName("UARTESParam") - .setParameters(Arrays.asList( - new Parameter().setName("ParameterInt16").setType(PropertyProvider.nameInt16))) - .setReturnType( - new ReturnType().setType(EntityTypeProvider.nameETKeyNav).setCollection(true)) + new Action().setName(nameUARTETAllPrimParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterDate").setType(PropertyProvider.nameDate))) + .setReturnType( + new ReturnType().setType(EntityTypeProvider.nameETAllPrim)) ); + } else if (actionName.equals(nameUARTCollETAllPrimParam)) { + return Arrays.asList( + new Action().setName(nameUARTCollETAllPrimParam.getName()) + .setParameters(Arrays.asList( + new Parameter().setName("ParameterTimeOfDay").setType(PropertyProvider.nameInt16))) + .setReturnType( + new ReturnType().setType(EntityTypeProvider.nameETAllPrim).setCollection(true)) + ); + } else if (actionName.equals(nameBAETTwoKeyNavRTETTwoKeyNav)) { return Arrays.asList( new Action().setName("BAETTwoKeyNavRTETTwoKeyNav") 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 dfdd4e2c5..84ec4c4e8 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 @@ -36,6 +36,14 @@ import java.util.List; public class ContainerProvider { public static final FullQualifiedName nameContainer = new FullQualifiedName(SchemaProvider.NAMESPACE, "Container"); + public static final String AIRT_STRING = "AIRTString"; + public static final String AIRT_COLL_STRING_TWO_PARAM = "AIRTCollStringTwoParam"; + public static final String AIRTCT_TWO_PRIM_PARAM = "AIRTCTTwoPrimParam"; + public static final String AIRT_COLL_CT_TWO_PRIM_PARAM = "AIRTCollCTTwoPrimParam"; + public static final String AIRTET_TWO_KEY_TWO_PRIM_PARAM = "AIRTETTwoKeyTwoPrimParam"; + public static final String AIRT_COLL_ET_KEY_NAV_PARAM = "AIRTCollETKeyNavParam"; + public static final String AIRTES_ALL_PRIM_PARAM = "AIRTESAllPrimParam"; + public static final String AIRT_COLL_ES_ALL_PRIM_PARAM = "AIRTCollESAllPrimParam"; EntityContainerInfo entityContainerInfoTest1 = new EntityContainerInfo().setContainerName(nameContainer); @@ -98,13 +106,14 @@ 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")); - actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTCompCollParam")); - actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTETParam")); - actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, "AIRTETCollAllPrimParam")); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRT_STRING)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRT_COLL_STRING_TWO_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRTCT_TWO_PRIM_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRT_COLL_CT_TWO_PRIM_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRTET_TWO_KEY_TWO_PRIM_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRT_COLL_ET_KEY_NAV_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRTES_ALL_PRIM_PARAM)); + actionImports.add(prov.getActionImport(ContainerProvider.nameContainer, AIRT_COLL_ES_ALL_PRIM_PARAM)); // FunctionImports List functionImports = new ArrayList(); @@ -259,43 +268,48 @@ public class ContainerProvider { return null; } - public ActionImport getActionImport(final FullQualifiedName entityContainer, final String name) throws ODataException - { + public ActionImport getActionImport(final FullQualifiedName entityContainer, final String name) + throws ODataException { if (entityContainer.equals(nameContainer)) { - if (name.equals("AIRTString")) { + if (name.equals(AIRT_STRING)) { return new ActionImport() - .setName("AIRTString") + .setName(AIRT_STRING) .setAction(ActionProvider.nameUARTString); - } else if (name.equals("AIRTPrimParam")) { + } else if (name.equals(AIRT_COLL_STRING_TWO_PARAM)) { return new ActionImport() - .setName("AIRTPrimParam") - .setAction(ActionProvider.nameUARTPrimParam); + .setName(AIRT_COLL_STRING_TWO_PARAM) + .setAction(ActionProvider.nameUARTCollStringTwoParam); - } else if (name.equals("AIRTPrimCollParam")) { + } else if (name.equals(AIRTCT_TWO_PRIM_PARAM)) { return new ActionImport() - .setName("AIRTPrimCollParam") - .setAction(ActionProvider.nameUARTPrimCollParam); + .setName(AIRTCT_TWO_PRIM_PARAM) + .setAction(ActionProvider.nameUARTCTTwoPrimParam); - } else if (name.equals("AIRTCompParam")) { + } else if (name.equals(AIRT_COLL_CT_TWO_PRIM_PARAM)) { return new ActionImport() - .setName("AIRTCompParam") - .setAction(ActionProvider.nameUARTCompParam); + .setName(AIRT_COLL_CT_TWO_PRIM_PARAM) + .setAction(ActionProvider.nameUARTCollCTTwoPrimParam); - } else if (name.equals("AIRTCompCollParam")) { + } else if (name.equals(AIRTET_TWO_KEY_TWO_PRIM_PARAM)) { return new ActionImport() - .setName("AIRTCompCollParam") - .setAction(ActionProvider.nameUARTCompCollParam); + .setName(AIRTET_TWO_KEY_TWO_PRIM_PARAM) + .setAction(ActionProvider.nameUARTETTwoKeyTwoPrimParam); - } else if (name.equals("AIRTETParam")) { + } else if (name.equals(AIRT_COLL_ET_KEY_NAV_PARAM)) { return new ActionImport() - .setName("AIRTETParam") - .setAction(ActionProvider.nameUARTETParam); + .setName(AIRT_COLL_ET_KEY_NAV_PARAM) + .setAction(ActionProvider.nameUARTCollETKeyNavParam); - } else if (name.equals("AIRTETCollAllPrimParam")) { + } else if (name.equals(AIRTES_ALL_PRIM_PARAM)) { return new ActionImport() - .setName("AIRTETCollAllPrimParam") - .setAction(ActionProvider.nameUARTESParam); + .setName(AIRTES_ALL_PRIM_PARAM) + .setAction(ActionProvider.nameUARTETAllPrimParam); + + } else if (name.equals(AIRT_COLL_ES_ALL_PRIM_PARAM)) { + return new ActionImport() + .setName(AIRT_COLL_ES_ALL_PRIM_PARAM) + .setAction(ActionProvider.nameUARTCollETAllPrimParam); } } 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 480685736..d2c19551b 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 @@ -108,12 +108,13 @@ public class SchemaProvider { 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)); - actions.addAll(prov.getActions(ActionProvider.nameUARTCompCollParam)); - actions.addAll(prov.getActions(ActionProvider.nameUARTETParam)); - actions.addAll(prov.getActions(ActionProvider.nameUARTESParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTCollStringTwoParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTCTTwoPrimParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTCollCTTwoPrimParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTETTwoKeyTwoPrimParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTCollETKeyNavParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTETAllPrimParam)); + actions.addAll(prov.getActions(ActionProvider.nameUARTCollETAllPrimParam)); // Functions List functions = new ArrayList(); 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 03e521333..c7181d809 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 @@ -67,6 +67,7 @@ import org.apache.olingo.server.api.processor.ReferenceCollectionProcessor; import org.apache.olingo.server.api.processor.ReferenceProcessor; import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.tecsvc.provider.ContainerProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Test; @@ -318,21 +319,57 @@ public class ODataHandlerTest { @Test public void dispatchAction() throws Exception { - final String uri = "AIRTString"; - - PrimitiveProcessor processor = mock(PrimitiveProcessor.class); - dispatch(HttpMethod.POST, uri, processor); - verify(processor).processPrimitive( + PrimitiveProcessor primitiveProcessor = mock(PrimitiveProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRT_STRING, primitiveProcessor); + verify(primitiveProcessor).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)); + PrimitiveCollectionProcessor primitiveCollectionProcessor = mock(PrimitiveCollectionProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_STRING_TWO_PARAM, primitiveCollectionProcessor); + verify(primitiveCollectionProcessor).processPrimitiveCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); - dispatchMethodNotAllowed(HttpMethod.GET, uri, processor); + ComplexProcessor complexProcessor = mock(ComplexProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRTCT_TWO_PRIM_PARAM, complexProcessor); + verify(complexProcessor).processComplex( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + ComplexCollectionProcessor complexCollectionProcessor = mock(ComplexCollectionProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_CT_TWO_PRIM_PARAM, complexCollectionProcessor); + verify(complexCollectionProcessor).processComplexCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + EntityProcessor entityProcessor = mock(EntityProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRTET_TWO_KEY_TWO_PRIM_PARAM, entityProcessor); + verify(entityProcessor).processEntity( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + EntityCollectionProcessor entityCollectionProcessor = mock(EntityCollectionProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_ET_KEY_NAV_PARAM, entityCollectionProcessor); + verify(entityCollectionProcessor).processEntityCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + EntityProcessor entityProcessorEs = mock(EntityProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRTES_ALL_PRIM_PARAM, entityProcessorEs); + verify(entityProcessorEs).processEntity( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + EntityCollectionProcessor entityCollectionProcessorEs = mock(EntityCollectionProcessor.class); + dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_ES_ALL_PRIM_PARAM, entityCollectionProcessorEs); + verify(entityCollectionProcessorEs).processEntityCollection( + any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), + any(ContentType.class), any(ContentType.class)); + + dispatchMethodNotAllowed(HttpMethod.GET, "AIRTString", mock(Processor.class)); } - + @Test public void dispatchEntity() throws Exception { final String uri = "ESAllPrim(0)"; diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentTest.java index 5055b6b3a..2ee632061 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/xml/MetadataDocumentTest.java @@ -89,9 +89,9 @@ public class MetadataDocumentTest { // TODO: TypeDefinition // assertThat(metadata, containsString("")); - assertThat(metadata, containsString("" + assertThat(metadata, containsString("" + "" - + "")); + + "")); assertThat(metadata, containsString("" @@ -120,7 +120,7 @@ public class MetadataDocumentTest { + "")); assertThat(metadata, - containsString("")); + containsString("")); assertThat(metadata, containsString("", expression.accept(new FilterTreeToText())); + assertEquals("", expression.accept(new FilterTreeToText())); // UriResourceImplTyped check collection = false case assertEquals(false, expression.isCollection()); // UriResourceImplTyped check collection = true case - action = edm.getUnboundAction(ActionProvider.nameUARTPrimCollParam); + action = edm.getUnboundAction(ActionProvider.nameUARTCollStringTwoParam); expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart( new UriResourceActionImpl().setAction(action)) .asUriInfoResource()); assertEquals(true, expression.isCollection()); // UriResourceImplTyped with filter - action = edm.getUnboundAction(ActionProvider.nameUARTPrimParam); + action = edm.getUnboundAction(ActionProvider.nameUARTString); expression.setResourcePath(new UriInfoImpl().setKind(UriInfoKind.resource).addResourcePart( new UriResourceActionImpl().setAction(action).setTypeFilter(entityType)) .asUriInfoResource()); diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java index 9ad799af7..bdde9ce4c 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/uri/validator/UriValidatorTest.java @@ -27,6 +27,7 @@ import org.apache.olingo.server.core.uri.parser.UriParserException; import org.apache.olingo.server.core.uri.parser.UriParserSemanticException; import org.apache.olingo.server.core.uri.parser.UriParserSyntaxException; import org.apache.olingo.server.core.uri.testutil.TestUriValidator; +import org.apache.olingo.server.tecsvc.provider.ContainerProvider; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Test; @@ -152,9 +153,9 @@ public class UriValidatorTest { { "ESTwoKeyNav/olingo.odata.test1.BAESTwoKeyNavRTESTwoKeyNav" }, { "ESAllPrim/olingo.odata.test1.BAESAllPrimRTETAllPrim" }, - { "AIRTPrimCollParam" }, - { "AIRTETParam" }, - { "AIRTPrimParam" } + { ContainerProvider.AIRT_COLL_STRING_TWO_PARAM }, + { ContainerProvider.AIRTET_TWO_KEY_TWO_PRIM_PARAM }, + { ContainerProvider.AIRT_STRING } }; private String[][] urisWithNonValidSystemQueryOptions = { diff --git a/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java b/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java index f3747dcbd..85a8c6293 100644 --- a/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java +++ b/samples/server/src/main/java/org/apache/olingo/server/sample/processor/CarsProcessor.java @@ -55,9 +55,7 @@ import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions import org.apache.olingo.server.api.serializer.EntitySerializerOptions; import org.apache.olingo.server.api.serializer.ODataSerializer; import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions; -import org.apache.olingo.server.api.serializer.RepresentationType; import org.apache.olingo.server.api.serializer.SerializerException; -import org.apache.olingo.server.api.uri.UriHelper; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriResource; @@ -122,6 +120,15 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor response.setHeader(HttpHeader.CONTENT_TYPE, requestedContentType.toContentTypeString()); } + @Override + public void processEntityCollection(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, + final ContentType requestFormat, final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process entity collection is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void readEntity(final ODataRequest request, ODataResponse response, final UriInfo uriInfo, final ContentType requestedContentType) throws ODataApplicationException, SerializerException { @@ -171,6 +178,15 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor throw new UnsupportedOperationException("Not yet implemented"); } + @Override + public void processEntity(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, final ContentType requestFormat, + final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Process entity is not supported yet.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + @Override public void readPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType format) throws ODataApplicationException, SerializerException { @@ -341,7 +357,7 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { - throw new ODataApplicationException("Process Primitive property update is not supported yet.", + throw new ODataApplicationException("Process Primitive property is not supported yet.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } @@ -359,7 +375,7 @@ public class CarsProcessor implements EntityCollectionProcessor, EntityProcessor final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { - throw new ODataApplicationException("Process Complex property update is not supported yet.", + throw new ODataApplicationException("Process Complex property is not supported yet.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } From 40e0ae5ecd4e6146d57b04cbc570edde82ce6a54 Mon Sep 17 00:00:00 2001 From: Michael Bolz Date: Wed, 14 Jan 2015 06:34:52 +0100 Subject: [PATCH 5/5] [OLINGO-507] Created seperate Action_ interfaces --- .../ActionComplexCollectionProcessor.java | 48 +++++++++++++++++++ .../api/processor/ActionComplexProcessor.java | 48 +++++++++++++++++++ .../ActionEntityCollectionProcessor.java | 48 +++++++++++++++++++ .../api/processor/ActionEntityProcessor.java | 48 +++++++++++++++++++ .../ActionPrimitiveCollectionProcessor.java | 48 +++++++++++++++++++ .../processor/ActionPrimitiveProcessor.java | 48 +++++++++++++++++++ .../processor/ComplexCollectionProcessor.java | 14 ------ .../api/processor/ComplexProcessor.java | 15 ------ .../processor/EntityCollectionProcessor.java | 14 ------ .../server/api/processor/EntityProcessor.java | 14 ------ .../PrimitiveCollectionProcessor.java | 16 ------- .../api/processor/PrimitiveProcessor.java | 14 ------ .../olingo/server/core/ODataHandler.java | 29 ++++++----- .../processor/TechnicalEntityProcessor.java | 9 ++-- .../TechnicalPrimitiveComplexProcessor.java | 30 ++++++++---- .../olingo/server/core/ODataHandlerTest.java | 40 +++++++++------- 16 files changed, 355 insertions(+), 128 deletions(-) create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexCollectionProcessor.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexProcessor.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityCollectionProcessor.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityProcessor.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveCollectionProcessor.java create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveProcessor.java diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexCollectionProcessor.java new file mode 100644 index 000000000..31c525faa --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexCollectionProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of ComplexCollection. + */ +public interface ActionComplexCollectionProcessor extends ComplexCollectionProcessor { + /** + * 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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionComplexCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexProcessor.java new file mode 100644 index 000000000..11e83453e --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionComplexProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of Complex. + */ +public interface ActionComplexProcessor extends ComplexProcessor { + /** + * 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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityCollectionProcessor.java new file mode 100644 index 000000000..edabfcee1 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityCollectionProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of Entity Collection. + */ +public interface ActionEntityCollectionProcessor extends EntityCollectionProcessor { + /** + * Process an action which has as return type a collection of entities. + * @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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionEntityCollection(ODataRequest request, ODataResponse response, + UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityProcessor.java new file mode 100644 index 000000000..8a2043eff --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionEntityProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of Entity. + */ +public interface ActionEntityProcessor extends EntityProcessor { + /** + * Process an action which has as return type an entity. + * @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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveCollectionProcessor.java new file mode 100644 index 000000000..9fd7549e5 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveCollectionProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of Primitive Collection. + */ +public interface ActionPrimitiveCollectionProcessor extends PrimitiveCollectionProcessor { + /** + * 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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveProcessor.java new file mode 100644 index 000000000..362621b03 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/ActionPrimitiveProcessor.java @@ -0,0 +1,48 @@ +/* + * 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.server.api.processor; + +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.uri.UriInfo; + +/** + * Processor interface for handling an action import request which has a + * return type of Primitive. + */ +public interface ActionPrimitiveProcessor extends PrimitiveProcessor { + /** + * 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 org.apache.olingo.server.api.ODataApplicationException if the service implementation encounters a failure + * @throws org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed + * @throws org.apache.olingo.server.api.serializer.SerializerException if serialization failed + */ + void processActionPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException; +} 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 f6e3e794f..1fe0b0c99 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,20 +63,6 @@ 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 3c7466067..58d9bc8e1 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 @@ -60,21 +60,6 @@ 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/EntityCollectionProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java index 91fb94ce7..09043a3a6 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityCollectionProcessor.java @@ -43,18 +43,4 @@ public interface EntityCollectionProcessor extends Processor { void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException; - /** - * Process an action which has as return type a collection of entities. - * @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 org.apache.olingo.server.api.deserializer.DeserializerException if deserialization failed - * @throws SerializerException if serialization failed - */ - void processEntityCollection(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/EntityProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java index 06d88f349..dbce4f2a5 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/EntityProcessor.java @@ -82,18 +82,4 @@ public interface EntityProcessor extends Processor { */ void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException; - /** - * Process an action which has as return type an entity. - * @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 processEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, - ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException; } 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 9770b3b6e..07f367855 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,20 +75,4 @@ 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 86eee10fe..8c240607a 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 @@ -73,18 +73,4 @@ 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 d14717c4f..4528d3a72 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 @@ -42,6 +42,12 @@ import org.apache.olingo.server.api.ODataServerError; import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.batch.exception.BatchDeserializerException; import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionComplexProcessor; +import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionEntityProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveProcessor; import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.api.processor.ComplexCollectionProcessor; import org.apache.olingo.server.api.processor.ComplexProcessor; @@ -476,11 +482,11 @@ public class ODataHandler { final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, complexRepresentationType); if (complexRepresentationType == RepresentationType.COMPLEX) { - selectProcessor(ComplexProcessor.class) - .processComplex(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionComplexProcessor.class) + .processActionComplex(request, response, uriInfo, requestFormat, responseFormat); } else { - selectProcessor(ComplexCollectionProcessor.class) - .processComplexCollection(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionComplexCollectionProcessor.class) + .processActionComplexCollection(request, response, uriInfo, requestFormat, responseFormat); } } else if (method == HttpMethod.DELETE) { if (complexRepresentationType == RepresentationType.COMPLEX) { @@ -535,11 +541,11 @@ public class ODataHandler { final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, representationType); if (representationType == RepresentationType.PRIMITIVE) { - selectProcessor(PrimitiveProcessor.class) - .processPrimitive(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionPrimitiveProcessor.class) + .processActionPrimitive(request, response, uriInfo, requestFormat, responseFormat); } else { - selectProcessor(PrimitiveCollectionProcessor.class) - .processPrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionPrimitiveCollectionProcessor.class) + .processActionPrimitiveCollection(request, response, uriInfo, requestFormat, responseFormat); } } else { throw new ODataHandlerException("HTTP method " + method + " is not allowed.", @@ -601,8 +607,8 @@ public class ODataHandler { checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); - selectProcessor(EntityCollectionProcessor.class) - .processEntityCollection(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionEntityCollectionProcessor.class) + .processActionEntityCollection(request, response, uriInfo, requestFormat, responseFormat); } else { checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), @@ -631,7 +637,8 @@ public class ODataHandler { checkContentTypeSupport(requestFormat, RepresentationType.ENTITY); final ContentType responseFormat = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), request, customContentTypeSupport, RepresentationType.ENTITY); - selectProcessor(EntityProcessor.class).processEntity(request, response, uriInfo, requestFormat, responseFormat); + selectProcessor(ActionEntityProcessor.class).processActionEntity( + request, response, uriInfo, requestFormat, responseFormat); } else if (method == HttpMethod.DELETE) { selectProcessor(isMedia ? MediaEntityProcessor.class : EntityProcessor.class) .deleteEntity(request, response, uriInfo); diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index e5bd0ff76..f86a64c1d 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -35,6 +35,8 @@ import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionEntityProcessor; import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityCollectionProcessor; import org.apache.olingo.server.api.processor.EntityProcessor; @@ -55,7 +57,8 @@ import org.apache.olingo.server.tecsvc.data.DataProvider; * Technical Processor for entity-related functionality. */ public class TechnicalEntityProcessor extends TechnicalProcessor - implements EntityCollectionProcessor, CountEntityCollectionProcessor, EntityProcessor, MediaEntityProcessor { + implements EntityCollectionProcessor, ActionEntityCollectionProcessor, CountEntityCollectionProcessor, + EntityProcessor, ActionEntityProcessor, MediaEntityProcessor { public TechnicalEntityProcessor(final DataProvider dataProvider) { super(dataProvider); @@ -90,7 +93,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } @Override - public void processEntityCollection(final ODataRequest request, final ODataResponse response, + public void processActionEntityCollection(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { @@ -257,7 +260,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } @Override - public void processEntity(final ODataRequest request, final ODataResponse response, + public void processActionEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { 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 a98a9887f..75e3dcc51 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 @@ -41,6 +41,10 @@ import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionComplexProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveProcessor; import org.apache.olingo.server.api.processor.ComplexCollectionProcessor; import org.apache.olingo.server.api.processor.ComplexProcessor; import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor; @@ -68,8 +72,10 @@ import org.apache.olingo.server.tecsvc.data.DataProvider; * Technical Processor which provides functionality related to primitive and complex types and collections thereof. */ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor - implements PrimitiveProcessor, PrimitiveValueProcessor, PrimitiveCollectionProcessor, - ComplexProcessor, ComplexCollectionProcessor { + implements PrimitiveProcessor, PrimitiveValueProcessor, ActionPrimitiveProcessor, + PrimitiveCollectionProcessor, ActionPrimitiveCollectionProcessor, + ComplexProcessor, ActionComplexProcessor, + ComplexCollectionProcessor, ActionComplexCollectionProcessor { public TechnicalPrimitiveComplexProcessor(final DataProvider dataProvider) { super(dataProvider); @@ -96,8 +102,9 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor } @Override - public void processPrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, - ContentType requestFormat, ContentType responseFormat) + public void processActionPrimitive(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, + final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported yet.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); @@ -124,8 +131,10 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor } @Override - public void processPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType - requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, + public void processActionPrimitiveCollection(final ODataRequest request, final ODataResponse response, + final UriInfo uriInfo, + final ContentType requestFormat, final ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported yet.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); @@ -146,7 +155,7 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor } @Override - public void processComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType + public void processActionComplex(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported yet.", @@ -174,9 +183,10 @@ public class TechnicalPrimitiveComplexProcessor extends TechnicalProcessor } @Override - public void processComplexCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType - requestFormat, ContentType responseFormat) throws ODataApplicationException, DeserializerException, - SerializerException { + public void processActionComplexCollection(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); } 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 c7181d809..72d29568c 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 @@ -49,6 +49,12 @@ import org.apache.olingo.server.api.ServiceMetadata; import org.apache.olingo.server.api.edm.provider.EdmProvider; import org.apache.olingo.server.api.edm.provider.EntitySet; import org.apache.olingo.server.api.edmx.EdmxReference; +import org.apache.olingo.server.api.processor.ActionComplexCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionComplexProcessor; +import org.apache.olingo.server.api.processor.ActionEntityCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionEntityProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveCollectionProcessor; +import org.apache.olingo.server.api.processor.ActionPrimitiveProcessor; import org.apache.olingo.server.api.processor.BatchProcessor; import org.apache.olingo.server.api.processor.ComplexCollectionProcessor; import org.apache.olingo.server.api.processor.ComplexProcessor; @@ -319,57 +325,57 @@ public class ODataHandlerTest { @Test public void dispatchAction() throws Exception { - PrimitiveProcessor primitiveProcessor = mock(PrimitiveProcessor.class); + ActionPrimitiveProcessor primitiveProcessor = mock(ActionPrimitiveProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRT_STRING, primitiveProcessor); - verify(primitiveProcessor).processPrimitive( + verify(primitiveProcessor).processActionPrimitive( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - PrimitiveCollectionProcessor primitiveCollectionProcessor = mock(PrimitiveCollectionProcessor.class); + ActionPrimitiveCollectionProcessor primitiveCollectionProcessor = mock(ActionPrimitiveCollectionProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_STRING_TWO_PARAM, primitiveCollectionProcessor); - verify(primitiveCollectionProcessor).processPrimitiveCollection( + verify(primitiveCollectionProcessor).processActionPrimitiveCollection( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - ComplexProcessor complexProcessor = mock(ComplexProcessor.class); + ActionComplexProcessor complexProcessor = mock(ActionComplexProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRTCT_TWO_PRIM_PARAM, complexProcessor); - verify(complexProcessor).processComplex( + verify(complexProcessor).processActionComplex( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - ComplexCollectionProcessor complexCollectionProcessor = mock(ComplexCollectionProcessor.class); + ActionComplexCollectionProcessor complexCollectionProcessor = mock(ActionComplexCollectionProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_CT_TWO_PRIM_PARAM, complexCollectionProcessor); - verify(complexCollectionProcessor).processComplexCollection( + verify(complexCollectionProcessor).processActionComplexCollection( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - EntityProcessor entityProcessor = mock(EntityProcessor.class); + ActionEntityProcessor entityProcessor = mock(ActionEntityProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRTET_TWO_KEY_TWO_PRIM_PARAM, entityProcessor); - verify(entityProcessor).processEntity( + verify(entityProcessor).processActionEntity( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - EntityCollectionProcessor entityCollectionProcessor = mock(EntityCollectionProcessor.class); + ActionEntityCollectionProcessor entityCollectionProcessor = mock(ActionEntityCollectionProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_ET_KEY_NAV_PARAM, entityCollectionProcessor); - verify(entityCollectionProcessor).processEntityCollection( + verify(entityCollectionProcessor).processActionEntityCollection( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - EntityProcessor entityProcessorEs = mock(EntityProcessor.class); + ActionEntityProcessor entityProcessorEs = mock(ActionEntityProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRTES_ALL_PRIM_PARAM, entityProcessorEs); - verify(entityProcessorEs).processEntity( + verify(entityProcessorEs).processActionEntity( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); - EntityCollectionProcessor entityCollectionProcessorEs = mock(EntityCollectionProcessor.class); + ActionEntityCollectionProcessor entityCollectionProcessorEs = mock(ActionEntityCollectionProcessor.class); dispatch(HttpMethod.POST, ContainerProvider.AIRT_COLL_ES_ALL_PRIM_PARAM, entityCollectionProcessorEs); - verify(entityCollectionProcessorEs).processEntityCollection( + verify(entityCollectionProcessorEs).processActionEntityCollection( any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class), any(ContentType.class)); dispatchMethodNotAllowed(HttpMethod.GET, "AIRTString", mock(Processor.class)); } - + @Test public void dispatchEntity() throws Exception { final String uri = "ESAllPrim(0)";