From 97222fad310abc68adb0190eaabf598285098d48 Mon Sep 17 00:00:00 2001 From: Stephan Klevenz Date: Tue, 24 Jun 2014 17:20:48 +0200 Subject: [PATCH] [OLINGO-328] API design and setup of TDD --- .../olingo/server/api/ODataHttpHandler.java | 2 + .../api/processor/DefaultProcessor.java | 2 + .../server/api/processor/Processor.java | 2 + .../processor/SupportCustomContentTypes.java | 27 +++ .../server/core/DefaultRedirectProcessor.java | 4 + .../olingo/server/core/ODataHandler.java | 15 +- .../server/tecsvc/TechnicalServlet.java | 5 +- .../server/core/ContentNegotiationTest.java | 201 ++++++++++++++++++ .../olingo/server/core/ODataHandlerTest.java | 7 +- 9 files changed, 254 insertions(+), 11 deletions(-) create mode 100644 lib/server-api/src/main/java/org/apache/olingo/server/api/processor/SupportCustomContentTypes.java create mode 100644 lib/server-test/src/test/java/org/apache/olingo/server/core/ContentNegotiationTest.java diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataHttpHandler.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataHttpHandler.java index 8372f8036..e9d9caa7d 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataHttpHandler.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/ODataHttpHandler.java @@ -18,6 +18,8 @@ */ package org.apache.olingo.server.api; +import java.util.List; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java index e14e6d38c..4d1a94d25 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/DefaultProcessor.java @@ -19,6 +19,8 @@ package org.apache.olingo.server.api.processor; import java.io.InputStream; +import java.util.Collections; +import java.util.List; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.format.ODataFormat; diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/Processor.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/Processor.java index 014fba7cc..ef2b8a09c 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/Processor.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/Processor.java @@ -18,6 +18,8 @@ */ package org.apache.olingo.server.api.processor; +import java.util.List; + import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.server.api.OData; diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/SupportCustomContentTypes.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/SupportCustomContentTypes.java new file mode 100644 index 000000000..0a032e102 --- /dev/null +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/processor/SupportCustomContentTypes.java @@ -0,0 +1,27 @@ +/* + * 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 java.util.List; + +public interface SupportCustomContentTypes { + + public List getSupportedContentTypes(Class processorClass); + +} diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/DefaultRedirectProcessor.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/DefaultRedirectProcessor.java index 0d47d5562..400dd5544 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/DefaultRedirectProcessor.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/DefaultRedirectProcessor.java @@ -18,12 +18,16 @@ */ package org.apache.olingo.server.core; +import java.util.Collections; +import java.util.List; + import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.processor.Processor; public class DefaultRedirectProcessor implements RedirectProcessor { 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 a46281f06..f7248c392 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 @@ -18,6 +18,10 @@ */ package org.apache.olingo.server.core; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import org.apache.olingo.commons.api.ODataRuntimeException; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; @@ -27,7 +31,12 @@ import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.ODataRequest; import org.apache.olingo.server.api.ODataResponse; -import org.apache.olingo.server.api.processor.*; +import org.apache.olingo.server.api.processor.CollectionProcessor; +import org.apache.olingo.server.api.processor.DefaultProcessor; +import org.apache.olingo.server.api.processor.EntityProcessor; +import org.apache.olingo.server.api.processor.MetadataProcessor; +import org.apache.olingo.server.api.processor.Processor; +import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; import org.apache.olingo.server.api.uri.UriInfo; import org.apache.olingo.server.api.uri.UriResource; import org.apache.olingo.server.api.uri.UriResourceNavigation; @@ -35,10 +44,6 @@ import org.apache.olingo.server.api.uri.UriResourcePartTyped; import org.apache.olingo.server.core.uri.parser.Parser; import org.apache.olingo.server.core.uri.validator.UriValidator; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - public class ODataHandler { private final OData odata; diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java index 9841dd8f9..f03350d9b 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/TechnicalServlet.java @@ -26,11 +26,10 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.olingo.commons.api.edm.Edm; -import org.apache.olingo.server.api.ODataHttpHandler; import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataHttpHandler; import org.apache.olingo.server.tecsvc.data.DataProvider; import org.apache.olingo.server.tecsvc.processor.SampleJsonProcessor; -import org.apache.olingo.server.tecsvc.processor.TechnicalProcessor; import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -59,7 +58,7 @@ public class TechnicalServlet extends HttpServlet { // handler.register(new TechnicalProcessor(dataProvider)); handler.register(new SampleJsonProcessor()); - + handler.process(req, resp); } diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/ContentNegotiationTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/ContentNegotiationTest.java new file mode 100644 index 000000000..db5b9847a --- /dev/null +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/ContentNegotiationTest.java @@ -0,0 +1,201 @@ +/* + * 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.core; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Matchers.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.mockito.Mockito.withSettings; + +import java.util.Arrays; +import java.util.List; + +import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpMethod; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.processor.CollectionProcessor; +import org.apache.olingo.server.api.processor.MetadataProcessor; +import org.apache.olingo.server.api.processor.Processor; +import org.apache.olingo.server.api.processor.ServiceDocumentProcessor; +import org.apache.olingo.server.api.processor.SupportCustomContentTypes; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; +import org.junit.Ignore; +import org.junit.Test; + +public class ContentNegotiationTest { + +// static final private String ACCEPT_CASE1 = "text/plain;q=0.5"; +// static final private String ACCEPT_CASE2 = "application/json;odata=verbose;q=0.2"; + + //@formatter:off (Eclipse formatter) + //CHECKSTYLE:OFF (Maven checkstyle) + + String[][] casesServiceDocument = { + /* expected $format accept supported */ + { "application/json", null, null, null }, + { "application/json", "json", null, null }, + { "application/json", "json", "application/json", null }, + { "application/json", null, "application/json", null }, + { "application/json", null, "*/*", null }, +// { "aaa", "aaa", null, "aaa, bbb" }, +// { "aaa", null, "*/*", "aaa, bbb" }, + }; + + String[][] casesMetadata = { + /* expected $format accept supported */ + { "application/xml", null, null, null }, + { "application/xml", "xml", null, null }, + { "application/xml", null, "application/xml", null }, + { "application/xml", "xml", "application/xml", null }, + { "application/xml", null, "*/*", null }, +// { "aaa", "aaa", null, "aaa, bbb" }, + }; + + String[][] casesEntitySet = { + /* expected $format accept supported */ + { "application/json", null, null, null }, + { "application/json", "json", null, null }, + { "application/json", "json", "application/json", null }, + { "application/json", null, "*/*", null }, + }; + + //CHECKSTYLE:ON + //@formatter:on + + private ODataHandler createHandler() { + OData odata = OData.newInstance(); + Edm edm = odata.createEdm(new EdmTechProvider()); + return new ODataHandler(odata, edm); + + } + + @Test + public void testServiceDocumentDefault() { + + for (String[] useCase : casesServiceDocument) { + ODataRequest request = new ODataRequest(); + request.setMethod(HttpMethod.GET); + request.setRawODataPath("/" + (useCase[1] == null ? "" : "?$format=" + useCase[1])); + + ODataResponse response = callHandler(useCase, request); + + assertEquals(useCase[0], response.getHeaders().get(HttpHeader.CONTENT_TYPE)); + } + } + + @Test + public void testMetadataDefault() { + + for (String[] useCase : casesMetadata) { + ODataRequest request = new ODataRequest(); + request.setMethod(HttpMethod.GET); + request.setRawODataPath("/$metadata" + (useCase[1] == null ? "" : "?$format=" + useCase[1])); + + ODataResponse response = callHandler(useCase, request); + + assertEquals(useCase[0], response.getHeaders().get(HttpHeader.CONTENT_TYPE)); + } + } + + @Test + public void testEntitySet() { + + for (String[] useCase : casesEntitySet) { + ODataRequest request = new ODataRequest(); + request.setMethod(HttpMethod.GET); + request.setRawODataPath("/ESAllPrim" + (useCase[1] == null ? "" : "?$format=" + useCase[1])); + + ODataResponse response = callHandler(useCase, request, new CollectionProcessorStub()); + + assertEquals(useCase[0], response.getHeaders().get(HttpHeader.CONTENT_TYPE)); + } + } + + private ODataResponse callHandler(String[] useCase, ODataRequest request, + Processor defaultProcessor) { + ODataHandler handler = createHandler(); + + if (useCase[3] != null) { + ProcessorStub stub = new ProcessorStub(useCase[3].split(",")); + handler.register(stub); + } else { + if (defaultProcessor != null) { + handler.register(defaultProcessor); + } + } + + ODataResponse response = handler.process(request); + return response; + } + + ODataResponse callHandler(String[] useCase, ODataRequest request) { + return callHandler(useCase, request, null); + } + + private class ProcessorStub implements ServiceDocumentProcessor, MetadataProcessor, CollectionProcessor, + SupportCustomContentTypes { + + String[] formats; + + ProcessorStub(String[] strings) { + this.formats = strings; + } + + @Override + public void init(OData odata, Edm edm) {} + + @Override + public List getSupportedContentTypes(Class processorClass) { + return Arrays.asList(formats); + } + + @Override + public void readServiceDocument(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) { + response.setHeader(HttpHeader.CONTENT_TYPE, format); + } + + @Override + public void readCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) { + response.setHeader(HttpHeader.CONTENT_TYPE, format); + } + + @Override + public void readMetadata(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) { + response.setHeader(HttpHeader.CONTENT_TYPE, format); + } + + } + + private class CollectionProcessorStub implements CollectionProcessor { + + @Override + public void init(OData odata, Edm edm) {} + + @Override + public void readCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) { + response.setHeader(HttpHeader.CONTENT_TYPE, format); + } + } + +} 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 78ef17739..6e825bbb5 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 @@ -47,10 +47,10 @@ public class ODataHandlerTest { @Before public void before() { - OData server = OData.newInstance(); - Edm edm = server.createEdm(new EdmTechProvider()); + OData odata = OData.newInstance(); + Edm edm = odata.createEdm(new EdmTechProvider()); - handler = new ODataHandler(server, edm); + handler = new ODataHandler(odata, edm); } @Test @@ -182,4 +182,5 @@ public class ODataHandlerTest { assertEquals(ODataServiceVersion.V40.toString(), response.getHeaders().get(HttpHeader.ODATA_VERSION)); } + }