[OLINGO-507] nearly complete server dispatching

Change-Id: I4c337f5e8f9b3caeaa14fc658464baa3f4bf1df8

Signed-off-by: Christian Amend <chrisam@apache.org>
This commit is contained in:
Klaus Straubinger 2014-12-19 16:31:14 +01:00 committed by Christian Amend
parent 574a65037a
commit 883c89c140
6 changed files with 296 additions and 53 deletions

View File

@ -18,7 +18,6 @@
*/
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;
@ -36,11 +35,9 @@ public interface CountPrimitiveCollectionProcessor extends Processor {
* @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 responseFormat requested content type after content negotiation
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws SerializerException if serialization failed
*/
void countPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo,
ContentType responseFormat)
void countPrimitiveCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo)
throws ODataApplicationException, SerializerException;
}

View File

@ -45,33 +45,27 @@ public interface ReferenceProcessor extends Processor {
/**
* Creates entity reference in the persistence and puts content, status, and Location into the response.
* @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
* @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
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws DeserializerException if de-serialization failed
* @throws SerializerException if serialization failed
*/
void createReference(ODataRequest request, ODataResponse response, UriInfo uriInfo,
ContentType requestFormat, ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException;
void createReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat)
throws ODataApplicationException, DeserializerException;
/**
* Update entity reference in the persistence and puts content, status, and Location into the response.
* @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
* @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
* @throws ODataApplicationException if the service implementation encounters a failure
* @throws DeserializerException if de-serialization failed
* @throws SerializerException if serialization failed
*/
void updateReference(ODataRequest request, ODataResponse response, UriInfo uriInfo,
ContentType requestFormat, ContentType responseFormat)
throws ODataApplicationException, DeserializerException, SerializerException;
void updateReference(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat)
throws ODataApplicationException, DeserializerException;
/**
* Deletes reference to an entity from persistence and puts the status into the response.

View File

@ -138,4 +138,17 @@ public class ContentNegotiator {
}
return null;
}
public static void checkSupport(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;
}
}
throw new ContentNegotiatorException("unsupported content type: " + contentType,
ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, contentType.toContentTypeString());
}
}

View File

@ -41,7 +41,9 @@ import org.apache.olingo.server.api.deserializer.DeserializerException;
import org.apache.olingo.server.api.processor.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.CountPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.DefaultProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
@ -52,6 +54,8 @@ import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.PrimitiveValueProcessor;
import org.apache.olingo.server.api.processor.Processor;
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.serializer.CustomContentTypeSupport;
import org.apache.olingo.server.api.serializer.RepresentationType;
@ -61,6 +65,7 @@ import org.apache.olingo.server.api.uri.UriResource;
import org.apache.olingo.server.api.uri.UriResourceEntitySet;
import org.apache.olingo.server.api.uri.UriResourceNavigation;
import org.apache.olingo.server.api.uri.UriResourcePartTyped;
import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
import org.apache.olingo.server.api.uri.UriResourceProperty;
import org.apache.olingo.server.core.batchhandler.BatchHandler;
import org.apache.olingo.server.core.uri.parser.Parser;
@ -143,7 +148,7 @@ public class ODataHandler {
switch (uriInfo.getKind()) {
case metadata:
if (method.equals(HttpMethod.GET)) {
if (method == HttpMethod.GET) {
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, RepresentationType.METADATA);
selectProcessor(MetadataProcessor.class)
@ -154,7 +159,7 @@ public class ODataHandler {
}
break;
case service:
if (method.equals(HttpMethod.GET)) {
if (method == HttpMethod.GET) {
if ("".equals(request.getRawODataPath())) {
selectProcessor(RedirectProcessor.class).redirect(request, response);
} else {
@ -173,11 +178,14 @@ public class ODataHandler {
handleResourceDispatching(request, response);
break;
case batch:
final BatchProcessor bp = selectProcessor(BatchProcessor.class);
final BatchHandler handler = new BatchHandler(this, bp);
handler.process(request, response, true);
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",
@ -230,6 +238,7 @@ public class ODataHandler {
.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)
@ -247,8 +256,12 @@ public class ODataHandler {
selectProcessor(EntityProcessor.class)
.readEntity(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
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);
@ -265,10 +278,12 @@ public class ODataHandler {
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 {
throw new ODataHandlerException(
"Count of collections of primitive-type or complex-type instances is not implemented.",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
selectProcessor(CountComplexCollectionProcessor.class)
.countComplexCollection(request, response, uriInfo);
}
} else {
throw new ODataHandlerException("HTTP method " + method + " is not allowed for count.",
@ -291,8 +306,17 @@ public class ODataHandler {
.readPrimitiveCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
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)
@ -322,8 +346,17 @@ public class ODataHandler {
.readComplexCollection(request, response, uriInfo, requestedContentType);
}
} else if (method == HttpMethod.PUT || method == HttpMethod.PATCH) {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
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);
}
} else if (method == HttpMethod.DELETE) {
if (complexRepresentationType == RepresentationType.COMPLEX) {
selectProcessor(ComplexProcessor.class)
@ -341,19 +374,23 @@ public class ODataHandler {
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 RepresentationType valueRepresentationType =
(EdmPrimitiveType) ((UriResourceProperty) resource).getType() ==
EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.Binary) ?
RepresentationType.BINARY : RepresentationType.VALUE;
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(),
request, customContentTypeSupport, valueRepresentationType);
selectProcessor(PrimitiveValueProcessor.class)
.readPrimitiveValue(request, response, uriInfo, requestedContentType);
} else if (method == HttpMethod.PUT) {
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);
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);
@ -383,6 +420,43 @@ public class ODataHandler {
}
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());
}
} 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());
}
}
break;
default:
throw new ODataHandlerException("not implemented",
ODataHandlerException.MessageKeys.FUNCTIONALITY_NOT_IMPLEMENTED);

View File

@ -30,7 +30,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
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;
import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.server.api.ODataRequest;
@ -142,6 +144,31 @@ public class ContentNegotiatorTest {
}
}
@Test
public void checkSupport() throws Exception {
ContentNegotiator.checkSupport(ODataFormat.JSON.getContentType(ODataServiceVersion.V40), null,
RepresentationType.ENTITY);
ContentNegotiator.checkSupport(ContentType.TEXT_PLAIN, null, RepresentationType.VALUE);
try {
ContentNegotiator.checkSupport(ContentType.APPLICATION_SVG_XML, null, RepresentationType.ENTITY);
fail("Exception expected.");
} catch (final ContentNegotiatorException e) {
assertEquals(ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, e.getMessageKey());
}
ContentNegotiator.checkSupport(ContentType.create("a/b"), createCustomContentTypeSupport("a/b"),
RepresentationType.ENTITY);
ContentNegotiator.checkSupport(ContentType.create("a/b", "c=d"), createCustomContentTypeSupport("a/b"),
RepresentationType.ENTITY);
try {
ContentNegotiator.checkSupport(ContentType.create("a/b"), createCustomContentTypeSupport("a/b;c=d"),
RepresentationType.ENTITY);
fail("Exception expected.");
} catch (final ContentNegotiatorException e) {
assertEquals(ContentNegotiatorException.MessageKeys.UNSUPPORTED_CONTENT_TYPE, e.getMessageKey());
}
}
private void testContentNegotiation(final String[] useCase, final RepresentationType representationType)
throws ContentNegotiatorException {
@ -156,13 +183,8 @@ public class ContentNegotiatorTest {
request.addHeader(HttpHeader.ACCEPT, Arrays.asList(useCase[2]));
}
CustomContentTypeSupport customContentTypeSupport = null;
if (useCase[3] != null) {
customContentTypeSupport = mock(CustomContentTypeSupport.class);
when(customContentTypeSupport.modifySupportedContentTypes(
anyListOf(ContentType.class), any(RepresentationType.class)))
.thenReturn(createCustomContentTypes(useCase[3]));
}
final CustomContentTypeSupport customContentTypeSupport = useCase[3] == null ? null :
createCustomContentTypeSupport(useCase[3]);
final ContentType requestedContentType = ContentNegotiator.doContentNegotiation(
formatOption, request, customContentTypeSupport, representationType);
@ -173,7 +195,7 @@ public class ContentNegotiatorTest {
}
}
private List<ContentType> createCustomContentTypes(final String contentTypeString) {
private CustomContentTypeSupport createCustomContentTypeSupport(final String contentTypeString) {
final String[] contentTypes = contentTypeString.split(",");
List<ContentType> types = new ArrayList<ContentType>();
@ -181,6 +203,10 @@ public class ContentNegotiatorTest {
types.add(ContentType.create(contentTypes[i]));
}
return types;
CustomContentTypeSupport customContentTypeSupport = mock(CustomContentTypeSupport.class);
when(customContentTypeSupport.modifySupportedContentTypes(
anyListOf(ContentType.class), any(RepresentationType.class)))
.thenReturn(types);
return customContentTypeSupport;
}
}

View File

@ -25,6 +25,7 @@ import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import java.util.Collections;
@ -35,6 +36,7 @@ import org.apache.olingo.commons.api.ODataException;
import org.apache.olingo.commons.api.edm.FullQualifiedName;
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;
import org.apache.olingo.commons.api.http.HttpContentType;
import org.apache.olingo.commons.api.http.HttpHeader;
import org.apache.olingo.commons.api.http.HttpMethod;
@ -47,9 +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.BatchProcessor;
import org.apache.olingo.server.api.processor.ComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.ComplexProcessor;
import org.apache.olingo.server.api.processor.CountComplexCollectionProcessor;
import org.apache.olingo.server.api.processor.CountEntityCollectionProcessor;
import org.apache.olingo.server.api.processor.CountPrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
import org.apache.olingo.server.api.processor.EntityProcessor;
import org.apache.olingo.server.api.processor.MediaEntityProcessor;
@ -58,6 +63,8 @@ import org.apache.olingo.server.api.processor.PrimitiveCollectionProcessor;
import org.apache.olingo.server.api.processor.PrimitiveProcessor;
import org.apache.olingo.server.api.processor.PrimitiveValueProcessor;
import org.apache.olingo.server.api.processor.Processor;
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.EdmTechProvider;
@ -219,6 +226,20 @@ public class ODataHandlerTest {
assertEquals(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatusCode());
}
@Test
public void dispatchBatch() throws Exception {
final String uri = "$batch";
final BatchProcessor processor = mock(BatchProcessor.class);
dispatch(HttpMethod.POST, uri, processor);
// TODO: Verify that batch processing has been called.
dispatchMethodNotAllowed(HttpMethod.GET, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test
public void dispatchEntitySet() throws Exception {
final String uri = "ESAllPrim";
@ -266,6 +287,16 @@ public class ODataHandlerTest {
verify(processor).readEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateEntity(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteEntity(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -317,6 +348,16 @@ public class ODataHandlerTest {
verify(processor).readPrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -332,10 +373,17 @@ public class ODataHandlerTest {
verify(processor).readPrimitiveValue(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.PUT, uri, null, HttpHeader.CONTENT_TYPE, ContentType.TEXT_PLAIN.toContentTypeString(),
processor);
verify(processor).updatePrimitive(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitive(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
}
@Test
@ -347,12 +395,31 @@ public class ODataHandlerTest {
verify(processor).readPrimitiveCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updatePrimitiveCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deletePrimitiveCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
}
@Test
public void dispatchPrimitiveCollectionPropertyCount() throws Exception {
final String uri = "ESMixPrimCollComp(7)/CollPropertyString/$count";
final CountPrimitiveCollectionProcessor processor = mock(CountPrimitiveCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).countPrimitiveCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test
public void dispatchComplexProperty() throws Exception {
final String uri = "ESMixPrimCollComp(7)/PropertyComp";
@ -362,6 +429,16 @@ public class ODataHandlerTest {
verify(processor).readComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateComplex(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteComplex(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
@ -377,12 +454,72 @@ public class ODataHandlerTest {
verify(processor).readComplexCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateComplexCollection(
any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class), any(ContentType.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteComplexCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
}
@Test
public void dispatchComplexCollectionPropertyCount() throws Exception {
final String uri = "ESMixPrimCollComp(7)/CollPropertyComp/$count";
final CountComplexCollectionProcessor processor = mock(CountComplexCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).countComplexCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
@Test
public void dispatchReference() throws Exception {
final String uri = "ESAllPrim(0)/NavPropertyETTwoPrimOne/$ref";
final ReferenceProcessor processor = mock(ReferenceProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).readReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.PUT, uri, processor);
verify(processor).updateReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.PATCH, uri, processor);
verify(processor, times(2)).updateReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatch(HttpMethod.DELETE, uri, processor);
verify(processor).deleteReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class));
dispatch(HttpMethod.POST, uri.replace("One", "Many"), processor);
verify(processor).createReference(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.POST, uri, processor);
}
@Test
public void dispatchReferenceCollection() throws Exception {
final String uri = "ESAllPrim(0)/NavPropertyETTwoPrimMany/$ref";
final ReferenceCollectionProcessor processor = mock(ReferenceCollectionProcessor.class);
dispatch(HttpMethod.GET, uri, processor);
verify(processor).readReferenceCollection(any(ODataRequest.class), any(ODataResponse.class), any(UriInfo.class),
any(ContentType.class));
dispatchMethodNotAllowed(HttpMethod.PUT, uri, processor);
dispatchMethodNotAllowed(HttpMethod.PATCH, uri, processor);
dispatchMethodNotAllowed(HttpMethod.DELETE, uri, processor);
}
private ODataResponse dispatch(final HttpMethod method, final String path, final String query,
final String headerName, final String headerValue, final Processor processor) {
ODataRequest request = new ODataRequest();
@ -397,6 +534,8 @@ public class ODataHandlerTest {
if (headerName != null) {
request.addHeader(headerName, Collections.singletonList(headerValue));
}
request.addHeader(HttpHeader.CONTENT_TYPE, Collections.singletonList(
ODataFormat.JSON.getContentType(ODataServiceVersion.V40).toContentTypeString()));
final OData odata = OData.newInstance();
final ServiceMetadata metadata = odata.createServiceMetadata(