You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ch...@apache.org on 2015/04/04 19:05:36 UTC
[30/50] [abbrv] olingo-odata4 git commit: OLINGO-573: New processing
framework on server side with single interface with TripPin as example
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponse.java
new file mode 100644
index 0000000..a306551
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponse.java
@@ -0,0 +1,119 @@
+/*
+ * 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.responses;
+
+import java.util.Map;
+
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.ServiceMetadata;
+
+public abstract class ServiceResponse {
+ protected ServiceMetadata metadata;
+ protected ODataResponse response;
+ protected Map<String, String> preferences;
+ private boolean closed;
+ private boolean strictApplyPreferences = true;
+
+ public ServiceResponse(ServiceMetadata metadata, ODataResponse response,
+ Map<String, String> preferences) {
+ this.metadata = metadata;
+ this.response = response;
+ this.preferences = preferences;
+ }
+
+ public ODataResponse getODataResponse() {
+ return this.response;
+ }
+
+ protected boolean isClosed() {
+ return this.closed;
+ }
+
+ protected void close() {
+ if (!this.closed) {
+ if (this.strictApplyPreferences) {
+ if (!preferences.isEmpty()) {
+ assert(this.response.getHeaders().get("Preference-Applied") != null);
+ }
+ }
+ this.closed = true;
+ }
+ }
+
+ public void writeNoContent(boolean closeResponse) {
+ this.response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode());
+ if (closeResponse) {
+ close();
+ }
+ }
+
+ public void writeNotFound(boolean closeResponse) {
+ response.setStatusCode(HttpStatusCode.NOT_FOUND.getStatusCode());
+ if (closeResponse) {
+ close();
+ }
+ }
+
+ public void writeServerError(boolean closeResponse) {
+ response.setStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode());
+ if (closeResponse) {
+ close();
+ }
+ }
+
+ public void writeBadRequest(boolean closeResponse) {
+ response.setStatusCode(HttpStatusCode.BAD_REQUEST.getStatusCode());
+ if (closeResponse) {
+ close();
+ }
+ }
+
+ public void writeOK(String contentType) {
+ this.response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ this.response.setHeader(HttpHeader.CONTENT_TYPE, contentType);
+ }
+
+ public void writeHeader(String key, String value) {
+ if ("Preference-Applied".equals(key)) {
+ String previous = this.response.getHeaders().get(key);
+ if (previous != null) {
+ value = previous+";"+value;
+ }
+ this.response.setHeader(key, value);
+ } else {
+ this.response.setHeader(key, value);
+ }
+ }
+
+ /**
+ * When true; the "Preference-Applied" header is strictly checked.
+ * @param flag
+ */
+ public void setStrictlyApplyPreferences(boolean flag) {
+ this.strictApplyPreferences = flag;
+ }
+
+ public abstract void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException;
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
new file mode 100644
index 0000000..4f11cb8
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/ServiceResponseVisior.java
@@ -0,0 +1,71 @@
+/*
+ * 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.responses;
+
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataTranslatedException;
+
+@SuppressWarnings("unused")
+public class ServiceResponseVisior {
+
+ public void visit(CountResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(EntityResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(MetadataResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(NoContentResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(PrimitiveValueResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(PropertyResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(ServiceDocumentResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(StreamResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+
+ public void visit(EntitySetResponse response) throws ODataTranslatedException,
+ ODataApplicationException {
+ response.writeServerError(true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/StreamResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/StreamResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/StreamResponse.java
new file mode 100644
index 0000000..ec7db03
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/responses/StreamResponse.java
@@ -0,0 +1,54 @@
+/*
+ * 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.responses;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Collections;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.ServiceMetadata;
+
+public class StreamResponse extends ServiceResponse {
+
+ public StreamResponse(ServiceMetadata metadata, ODataResponse response) {
+ super(metadata, response, Collections.EMPTY_MAP);
+ }
+
+ public void writeStreamResponse(InputStream streamContent, ContentType contentType) {
+ this.response.setContent(streamContent);
+ writeOK(contentType.toContentTypeString());
+ close();
+ }
+
+ public void writeBinaryResponse(byte[] streamContent, ContentType contentType) {
+ this.response.setContent(new ByteArrayInputStream(streamContent));
+ writeOK(contentType.toContentTypeString());
+ close();
+ }
+
+ @Override
+ public void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
new file mode 100644
index 0000000..9749a6c
--- /dev/null
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/MetadataParserTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.FileReader;
+import java.util.List;
+
+import org.apache.olingo.commons.api.ODataException;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.Action;
+import org.apache.olingo.commons.api.edm.provider.ActionImport;
+import org.apache.olingo.commons.api.edm.provider.ComplexType;
+import org.apache.olingo.commons.api.edm.provider.EdmProvider;
+import org.apache.olingo.commons.api.edm.provider.EntitySet;
+import org.apache.olingo.commons.api.edm.provider.EntityType;
+import org.apache.olingo.commons.api.edm.provider.EnumType;
+import org.apache.olingo.commons.api.edm.provider.Function;
+import org.apache.olingo.commons.api.edm.provider.FunctionImport;
+import org.apache.olingo.commons.api.edm.provider.NavigationPropertyBinding;
+import org.apache.olingo.commons.api.edm.provider.Parameter;
+import org.apache.olingo.commons.api.edm.provider.Property;
+import org.apache.olingo.commons.api.edm.provider.Singleton;
+import org.junit.Before;
+import org.junit.Test;
+
+public class MetadataParserTest {
+ final String NS = "Microsoft.OData.SampleService.Models.TripPin";
+ final FullQualifiedName NSF = new FullQualifiedName(NS);
+
+ EdmProvider provider = null;
+
+ @Before
+ public void setUp() throws Exception {
+ MetadataParser parser = new MetadataParser();
+ provider = parser.buildEdmProvider(new FileReader("src/test/resources/trippin.xml"));
+ }
+
+ @Test
+ public void testAction() throws ODataException {
+ // test action
+ List<Action> actions = provider.getActions(new FullQualifiedName(NS, "ResetDataSource"));
+ assertNotNull(actions);
+ assertEquals(1, actions.size());
+ }
+
+ @Test
+ public void testFunction() throws ODataException {
+ // test function
+ List<Function> functions = provider
+ .getFunctions(new FullQualifiedName(NS, "GetFavoriteAirline"));
+ assertNotNull(functions);
+ assertEquals(1, functions.size());
+ assertEquals("GetFavoriteAirline", functions.get(0).getName());
+ assertTrue(functions.get(0).isBound());
+ assertTrue(functions.get(0).isComposable());
+ assertEquals(
+ "person/Trips/PlanItems/Microsoft.OData.SampleService.Models.TripPin.Flight/Airline",
+ functions.get(0).getEntitySetPath());
+
+ List<Parameter> parameters = functions.get(0).getParameters();
+ assertNotNull(parameters);
+ assertEquals(1, parameters.size());
+ assertEquals("person", parameters.get(0).getName());
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Person",parameters.get(0).getType());
+ assertFalse(parameters.get(0).isNullable());
+
+ assertNotNull(functions.get(0).getReturnType());
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Airline",
+ functions.get(0).getReturnType().getType());
+ assertFalse(functions.get(0).getReturnType().isNullable());
+ }
+
+ @Test
+ public void testEnumType() throws ODataException {
+ // test enum type
+ EnumType enumType = provider.getEnumType(new FullQualifiedName(NS, "PersonGender"));
+ assertNotNull(enumType);
+ assertEquals("Male", enumType.getMembers().get(0).getName());
+ assertEquals("Female", enumType.getMembers().get(1).getName());
+ assertEquals("Unknown", enumType.getMembers().get(2).getName());
+ assertEquals("0", enumType.getMembers().get(0).getValue());
+ assertEquals("1", enumType.getMembers().get(1).getValue());
+ assertEquals("2", enumType.getMembers().get(2).getValue());
+ }
+
+ @Test
+ public void testEntityType() throws ODataException {
+ // test Entity Type
+ EntityType et = provider.getEntityType(new FullQualifiedName(NS, "Photo"));
+ assertNotNull(et);
+ assertNotNull(et.getKey());
+ assertEquals("Id", et.getKey().get(0).getName());
+ assertTrue(et.hasStream());
+ assertEquals("Id", et.getProperties().get(0).getName());
+ assertEquals("Edm.Int64", et.getProperties().get(0).getType());
+ assertEquals("Name", et.getProperties().get(1).getName());
+ assertEquals("Edm.String", et.getProperties().get(1).getType());
+ }
+
+ @Test
+ public void testComplexType() throws ODataException {
+ // Test Complex Type
+ ComplexType ct = provider.getComplexType(new FullQualifiedName(NS, "City"));
+ assertNotNull(ct);
+ assertEquals(3, ct.getProperties().size());
+ Property p = ct.getProperties().get(0);
+ assertEquals("CountryRegion", p.getName());
+ assertEquals("Edm.String", p.getType());
+ assertEquals(false, p.isNullable());
+
+ ct = provider.getComplexType(new FullQualifiedName(NS, "Location"));
+ assertNotNull(ct);
+
+ ct = provider.getComplexType(new FullQualifiedName(NS, "EventLocation"));
+ assertNotNull(ct);
+ }
+
+ @Test
+ public void testEntitySet() throws Exception {
+ EntitySet es = provider.getEntitySet(NSF, "People");
+ assertNotNull(es);
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Person",es.getType());
+
+ List<NavigationPropertyBinding> bindings = es.getNavigationPropertyBindings();
+ assertNotNull(bindings);
+ assertEquals(6, bindings.size());
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Flight/From", bindings.get(2)
+ .getPath());
+ assertEquals("Airports", bindings.get(2).getTarget());
+ }
+
+ @Test
+ public void testFunctionImport() throws Exception {
+ FunctionImport fi = provider.getFunctionImport(NSF, "GetNearestAirport");
+ assertNotNull(fi);
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.GetNearestAirport", fi.getFunction());
+ assertEquals("Airports", fi.getEntitySet());
+ assertTrue(fi.isIncludeInServiceDocument());
+ }
+
+ @Test
+ public void testActionImport() throws Exception {
+ ActionImport ai = provider.getActionImport(NSF, "ResetDataSource");
+ assertNotNull(ai);
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.ResetDataSource", ai.getAction());
+ assertNull(ai.getEntitySet());
+ }
+
+ @Test
+ public void testSingleton() throws Exception {
+ Singleton single = this.provider.getSingleton(NSF, "Me");
+ assertNotNull(single);
+
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Person",single.getType());
+
+ List<NavigationPropertyBinding> bindings = single.getNavigationPropertyBindings();
+ assertNotNull(bindings);
+ assertEquals(6, bindings.size());
+ assertEquals("Microsoft.OData.SampleService.Models.TripPin.Flight/From", bindings.get(2).getPath());
+ assertEquals("Airports", bindings.get(2).getTarget());
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
new file mode 100644
index 0000000..16caa1a
--- /dev/null
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/core/ServiceDispatcherTest.java
@@ -0,0 +1,417 @@
+/*
+ * 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 java.io.FileReader;
+import java.io.IOException;
+import java.net.URI;
+import java.util.Collections;
+import java.util.List;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.olingo.commons.api.edm.provider.EdmProvider;
+import org.apache.olingo.commons.api.http.HttpMethod;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataHttpHandler;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.core.requests.ActionRequest;
+import org.apache.olingo.server.core.requests.DataRequest;
+import org.apache.olingo.server.core.requests.FunctionRequest;
+import org.apache.olingo.server.core.requests.MediaRequest;
+import org.apache.olingo.server.core.requests.MetadataRequest;
+import org.apache.olingo.server.core.responses.CountResponse;
+import org.apache.olingo.server.core.responses.EntityResponse;
+import org.apache.olingo.server.core.responses.EntitySetResponse;
+import org.apache.olingo.server.core.responses.MetadataResponse;
+import org.apache.olingo.server.core.responses.NoContentResponse;
+import org.apache.olingo.server.core.responses.PrimitiveValueResponse;
+import org.apache.olingo.server.core.responses.PropertyResponse;
+import org.apache.olingo.server.core.responses.StreamResponse;
+import org.apache.olingo.server.example.TripPinServiceTest;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+public class ServiceDispatcherTest {
+ private Server server;
+
+ public class SampleODataServlet extends HttpServlet {
+ private final ServiceHandler handler; // must be stateless
+ private final EdmProvider provider; // must be stateless
+
+ public SampleODataServlet(ServiceHandler handler, EdmProvider provider) {
+ this.handler = handler;
+ this.provider = provider;
+ }
+
+ @Override
+ public void service(HttpServletRequest request, HttpServletResponse response)
+ throws IOException {
+ OData odata = OData4Impl.newInstance();
+ ServiceMetadata metadata = odata.createServiceMetadata(this.provider, Collections.EMPTY_LIST);
+
+ ODataHttpHandler handler = odata.createHandler(metadata);
+
+ handler.register(this.handler);
+ handler.process(request, response);
+ }
+ }
+
+ public int beforeTest(ServiceHandler serviceHandler) throws Exception {
+ MetadataParser parser = new MetadataParser();
+ EdmProvider edmProvider = parser.buildEdmProvider(new FileReader(
+ "src/test/resources/trippin.xml"));
+
+ this.server = new Server();
+
+ ServerConnector connector = new ServerConnector(this.server);
+ this.server.setConnectors(new Connector[] { connector });
+
+ ServletContextHandler context = new ServletContextHandler();
+ context.setContextPath("/trippin");
+ context
+ .addServlet(new ServletHolder(new SampleODataServlet(serviceHandler, edmProvider)), "/*");
+ this.server.setHandler(context);
+ this.server.start();
+
+ return connector.getLocalPort();
+ }
+
+ public void afterTest() throws Exception {
+ this.server.stop();
+ }
+
+ interface TestResult {
+ void validate() throws Exception;
+ }
+
+ private void helpGETTest(ServiceHandler handler, String path, TestResult validator)
+ throws Exception {
+ int port = beforeTest(handler);
+ HttpClient http = new HttpClient();
+ http.start();
+ http.GET("http://localhost:" + port + "/" + path);
+ validator.validate();
+ afterTest();
+ }
+
+ private void helpTest(ServiceHandler handler, String path, String method, String payload,
+ TestResult validator) throws Exception {
+ int port = beforeTest(handler);
+ HttpClient http = new HttpClient();
+ http.start();
+ String editUrl = "http://localhost:" + port + "/" + path;
+ http.newRequest(editUrl).method(method)
+ .header("Content-Type", "application/json;odata.metadata=minimal")
+ .content(TripPinServiceTest.content(payload)).send();
+ validator.validate();
+ afterTest();
+ }
+
+ @Test
+ public void testMetadata() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/$metadata", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<MetadataRequest> arg1 = ArgumentCaptor.forClass(MetadataRequest.class);
+ ArgumentCaptor<MetadataResponse> arg2 = ArgumentCaptor.forClass(MetadataResponse.class);
+ Mockito.verify(handler).readMetadata(arg1.capture(), arg2.capture());
+ }
+ });
+ }
+
+ @Test
+ public void testEntitySet() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<EntityResponse> arg2 = ArgumentCaptor.forClass(EntityResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ // Need toString on ContextURL class
+ // assertEquals("",
+ // request.getContextURL(request.getOdata()).toString());
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testEntitySetCount() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports/$count", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<CountResponse> arg2 = ArgumentCaptor.forClass(CountResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ // Need toString on ContextURL class
+ // assertEquals("",
+ // request.getContextURL(request.getOdata()).toString());
+ assertEquals("text/plain", request.getResponseContentType().toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testEntity() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports('0')", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<EntityResponse> arg2 = ArgumentCaptor.forClass(EntityResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals(1, request.getUriResourceEntitySet().getKeyPredicates().size());
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadProperty() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports('0')/IataCode", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<PropertyResponse> arg2 = ArgumentCaptor.forClass(PropertyResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals(true, request.isPropertyRequest());
+ assertEquals(false, request.isPropertyComplex());
+ assertEquals(1, request.getUriResourceEntitySet().getKeyPredicates().size());
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadComplexProperty() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports('0')/Location", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<PropertyResponse> arg2 = ArgumentCaptor.forClass(PropertyResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals(true, request.isPropertyRequest());
+ assertEquals(true, request.isPropertyComplex());
+ assertEquals(1, request.getUriResourceEntitySet().getKeyPredicates().size());
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadProperty$Value() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports('0')/IataCode/$value", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<PrimitiveValueResponse> arg2 = ArgumentCaptor
+ .forClass(PrimitiveValueResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals(true, request.isPropertyRequest());
+ assertEquals(false, request.isPropertyComplex());
+ assertEquals(1, request.getUriResourceEntitySet().getKeyPredicates().size());
+ assertEquals("text/plain", request.getResponseContentType().toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadPropertyRef() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Airports('0')/IataCode/$value", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<PrimitiveValueResponse> arg2 = ArgumentCaptor
+ .forClass(PrimitiveValueResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals(true, request.isPropertyRequest());
+ assertEquals(false, request.isPropertyComplex());
+ assertEquals(1, request.getUriResourceEntitySet().getKeyPredicates().size());
+ assertEquals("text/plain", request.getResponseContentType().toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testFunctionImport() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/GetNearestAirport(lat=12.11,lon=34.23)", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<FunctionRequest> arg1 = ArgumentCaptor.forClass(FunctionRequest.class);
+ ArgumentCaptor<PropertyResponse> arg3 = ArgumentCaptor.forClass(PropertyResponse.class);
+ ArgumentCaptor<HttpMethod> arg2 = ArgumentCaptor.forClass(HttpMethod.class);
+ Mockito.verify(handler).invoke(arg1.capture(), arg2.capture(), arg3.capture());
+
+ FunctionRequest request = arg1.getValue();
+ }
+ });
+ }
+
+ @Test
+ public void testActionImport() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpTest(handler, "trippin/ResetDataSource", "POST", "", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<ActionRequest> arg1 = ArgumentCaptor.forClass(ActionRequest.class);
+ ArgumentCaptor<NoContentResponse> arg2 = ArgumentCaptor.forClass(NoContentResponse.class);
+ Mockito.verify(handler).invoke(arg1.capture(), Mockito.anyString(), arg2.capture());
+
+ ActionRequest request = arg1.getValue();
+ }
+ });
+ }
+
+ @Test
+ public void testReadMedia() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/Photos(1)/$value", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<MediaRequest> arg1 = ArgumentCaptor.forClass(MediaRequest.class);
+ ArgumentCaptor<StreamResponse> arg2 = ArgumentCaptor.forClass(StreamResponse.class);
+ Mockito.verify(handler).readMediaStream(arg1.capture(), arg2.capture());
+
+ MediaRequest request = arg1.getValue();
+ assertEquals("application/octet-stream", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadNavigation() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/People('russelwhyte')/Friends", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<EntitySetResponse> arg2 = ArgumentCaptor.forClass(EntitySetResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testReadReference() throws Exception {
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpGETTest(handler, "trippin/People('russelwhyte')/Friends/$ref", new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<EntitySetResponse> arg2 = ArgumentCaptor.forClass(EntitySetResponse.class);
+ Mockito.verify(handler).read(arg1.capture(), arg2.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals("application/json;odata.metadata=minimal", request.getResponseContentType()
+ .toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testWriteReferenceCollection() throws Exception {
+ String payload = "{\n" + "\"@odata.id\": \"/Photos(11)\"\n" + "}";
+
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpTest(handler, "trippin/People('russelwhyte')/Friends/$ref", "POST", payload,
+ new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<String> arg2 = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<List> arg3 = ArgumentCaptor.forClass(List.class);
+ ArgumentCaptor<NoContentResponse> arg4 = ArgumentCaptor
+ .forClass(NoContentResponse.class);
+ Mockito.verify(handler).addReference(arg1.capture(), arg2.capture(), arg3.capture(),
+ arg4.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals("application/json;odata.metadata=minimal", request
+ .getResponseContentType().toContentTypeString());
+ }
+ });
+ }
+
+ @Test
+ public void testWriteReference() throws Exception {
+ String payload = "{\n" + "\"@odata.id\": \"/Photos(11)\"\n" + "}";
+
+ final ServiceHandler handler = Mockito.mock(ServiceHandler.class);
+ helpTest(handler, "trippin/People('russelwhyte')/Friends('someone')/Photo/$ref", "PUT", payload,
+ new TestResult() {
+ @Override
+ public void validate() throws Exception {
+ ArgumentCaptor<DataRequest> arg1 = ArgumentCaptor.forClass(DataRequest.class);
+ ArgumentCaptor<String> arg2 = ArgumentCaptor.forClass(String.class);
+ ArgumentCaptor<URI> arg3 = ArgumentCaptor.forClass(URI.class);
+ ArgumentCaptor<NoContentResponse> arg4 = ArgumentCaptor
+ .forClass(NoContentResponse.class);
+ Mockito.verify(handler).updateReference(arg1.capture(), arg2.capture(), arg3.capture(),
+ arg4.capture());
+
+ DataRequest request = arg1.getValue();
+ assertEquals("application/json;odata.metadata=minimal", request
+ .getResponseContentType().toContentTypeString());
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/2b73abcc/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
new file mode 100644
index 0000000..904f4d8
--- /dev/null
+++ b/lib/server-core-ext/src/test/java/org/apache/olingo/server/example/TripPinDataModel.java
@@ -0,0 +1,843 @@
+/*
+ * 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.example;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.EntitySet;
+import org.apache.olingo.commons.api.data.Link;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.edm.EdmEntityContainer;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.core.data.EntityImpl;
+import org.apache.olingo.commons.core.data.EntitySetImpl;
+import org.apache.olingo.commons.core.data.LinkImpl;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.deserializer.DeserializerException;
+import org.apache.olingo.server.api.uri.UriParameter;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.core.deserializer.json.ODataJsonDeserializer;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class TripPinDataModel {
+ private final ServiceMetadata metadata;
+ private HashMap<String, EntitySet> entitySetMap;
+ private Map<Integer, Map> tripLinks;
+ private Map<String, Map> peopleLinks;
+ private Map<Integer, Map> flightLinks;
+
+ public TripPinDataModel(ServiceMetadata metadata) throws Exception {
+ this.metadata = metadata;
+ loadData();
+ }
+
+ public void loadData() throws Exception {
+ this.entitySetMap = new HashMap<String, EntitySet>();
+ this.tripLinks = new HashMap<Integer, Map>();
+ this.peopleLinks = new HashMap<String, Map>();
+ this.flightLinks = new HashMap<Integer, Map>();
+
+ EdmEntityContainer ec = metadata.getEdm().getEntityContainer(null);
+ for (EdmEntitySet edmEntitySet : ec.getEntitySets()) {
+ String entitySetName = edmEntitySet.getName();
+ EntitySet set = loadEnities(entitySetName, edmEntitySet.getEntityType());
+ if (set != null) {
+ this.entitySetMap.put(entitySetName, set);
+ }
+ }
+
+ EdmEntityType type = metadata.getEdm().getEntityType(
+ new FullQualifiedName("Microsoft.OData.SampleService.Models.TripPin", "Trip"));
+ this.entitySetMap.put("Trip", loadEnities("Trip", type));
+
+ type = metadata.getEdm().getEntityType(
+ new FullQualifiedName("Microsoft.OData.SampleService.Models.TripPin", "Flight"));
+ this.entitySetMap.put("Flight", loadEnities("Flight", type));
+
+ type = metadata.getEdm().getEntityType(
+ new FullQualifiedName("Microsoft.OData.SampleService.Models.TripPin", "Event"));
+ this.entitySetMap.put("Event", loadEnities("Event", type));
+
+ ObjectMapper mapper = new ObjectMapper();
+ Map tripLinks = mapper.readValue(new FileInputStream(new File(
+ "src/test/resources/trip-links.json")), Map.class);
+ for (Object link : (ArrayList) tripLinks.get("value")) {
+ Map map = (Map) link;
+ this.tripLinks.put((Integer) map.get("TripId"), map);
+ }
+
+ Map peopleLinks = mapper.readValue(new FileInputStream(new File(
+ "src/test/resources/people-links.json")), Map.class);
+ for (Object link : (ArrayList) peopleLinks.get("value")) {
+ Map map = (Map) link;
+ this.peopleLinks.put((String) map.get("UserName"), map);
+ }
+
+ Map flightLinks = mapper.readValue(new FileInputStream(new File(
+ "src/test/resources/flight-links.json")), Map.class);
+ for (Object link : (ArrayList) flightLinks.get("value")) {
+ Map map = (Map) link;
+ this.flightLinks.put((Integer) map.get("PlanItemId"), map);
+ }
+ }
+
+ private EntitySet loadEnities(String entitySetName, EdmEntityType type) {
+ try {
+ ODataJsonDeserializer deserializer = new ODataJsonDeserializer();
+
+ EntitySet set = deserializer.entityCollection(new FileInputStream(new File(
+ "src/test/resources/" + entitySetName.toLowerCase() + ".json")), type);
+ // TODO: the count needs to be part of deserializer
+ set.setCount(set.getEntities().size());
+ for (Entity entity : set.getEntities()) {
+ ((EntityImpl) entity).setETag(UUID.randomUUID().toString());
+ ((EntityImpl) entity).setId(new URI(TripPinHandler.buildLocation(entity, entitySetName,
+ type)));
+ ((EntityImpl) entity).setType(type.getFullQualifiedName().getFullQualifiedNameAsString());
+ }
+ return set;
+ } catch (FileNotFoundException e) {
+ // keep going
+ e.printStackTrace();
+ } catch (DeserializerException e) {
+ // keep going
+ e.printStackTrace();
+ } catch (URISyntaxException e) {
+ // keep going
+ e.printStackTrace();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public EntitySet getEntitySet(String name) {
+ return getEntitySet(name, -1, -1);
+ }
+
+ public EntitySet getEntitySet(String name, int skip, int pageSize) {
+ EntitySet set = this.entitySetMap.get(name);
+ if (set == null) {
+ return null;
+ }
+
+ EntitySetImpl modifiedES = new EntitySetImpl();
+ int i = 0;
+ for (Entity e : set.getEntities()) {
+ if (skip >= 0 && i >= skip && modifiedES.getEntities().size() < pageSize) {
+ modifiedES.getEntities().add(e);
+ }
+ i++;
+ }
+ modifiedES.setCount(i);
+ set.setCount(i);
+
+ if (skip == -1 && pageSize == -1) {
+ return set;
+ }
+ return modifiedES;
+ }
+
+ private List<Entity> getMatch(UriParameter param, List<Entity> es)
+ throws ODataApplicationException {
+ ArrayList<Entity> list = new ArrayList<Entity>();
+ for (Entity entity : es) {
+
+ EdmEntityType entityType = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(entity.getType()));
+
+ EdmProperty property = (EdmProperty) entityType.getProperty(param.getName());
+ EdmType type = property.getType();
+ if (type.getKind() == EdmTypeKind.PRIMITIVE) {
+ Object match = readPrimitiveValue(property, param.getText());
+ Property entityValue = entity.getProperty(param.getName());
+ if (match.equals(entityValue.asPrimitive())) {
+ list.add(entity);
+ }
+ } else {
+ throw new RuntimeException("Can not compare complex objects");
+ }
+ }
+ return list;
+ }
+
+ static Object readPrimitiveValue(EdmProperty edmProperty, String value)
+ throws ODataApplicationException {
+ if (value == null) {
+ return null;
+ }
+ try {
+ if (value.startsWith("'") && value.endsWith("'")) {
+ value = value.substring(1,value.length()-1);
+ }
+ EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmProperty.getType();
+ Class<?> javaClass = getJavaClassForPrimitiveType(edmProperty, edmPrimitiveType);
+ return edmPrimitiveType.valueOfString(value, edmProperty.isNullable(),
+ edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(),
+ edmProperty.isUnicode(), javaClass);
+ } catch (EdmPrimitiveTypeException e) {
+ throw new ODataApplicationException("Invalid value: " + value + " for property: "
+ + edmProperty.getName(), 500, Locale.getDefault());
+ }
+ }
+
+ static Class<?> getJavaClassForPrimitiveType(EdmProperty edmProperty, EdmPrimitiveType edmPrimitiveType) {
+ Class<?> javaClass = null;
+ if (edmProperty.getMapping() != null && edmProperty.getMapping().getMappedJavaClass() != null) {
+ javaClass = edmProperty.getMapping().getMappedJavaClass();
+ } else {
+ javaClass = edmPrimitiveType.getDefaultType();
+ }
+
+ edmPrimitiveType.getDefaultType();
+ return javaClass;
+ }
+
+ public Entity getEntity(String name, List<UriParameter> keys) throws ODataApplicationException {
+ EntitySet es = getEntitySet(name);
+ return getEntity(es, keys);
+ }
+
+ public Entity getEntity(EntitySet es, List<UriParameter> keys) throws ODataApplicationException {
+ List<Entity> search = es.getEntities();
+ for (UriParameter param : keys) {
+ search = getMatch(param, search);
+ }
+ if (search.isEmpty()) {
+ return null;
+ }
+ return search.get(0);
+ }
+
+ private EntitySet getFriends(String userName) {
+ Map<String, Object> map = this.peopleLinks.get(userName);
+ if (map == null) {
+ return null;
+ }
+ ArrayList<String> friends = (ArrayList<String>) map.get("Friends");
+ EntitySet set = getEntitySet("People");
+
+ EntitySetImpl result = new EntitySetImpl();
+ int i = 0;
+ if (friends != null) {
+ for (String friend : friends) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("UserName").getValue().equals(friend)) {
+ result.getEntities().add(e);
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ result.setCount(i);
+ return result;
+ }
+
+ private EntitySet getTrips(String userName) {
+ Map<String, Object> map = this.peopleLinks.get(userName);
+ if (map == null) {
+ return null;
+ }
+
+ ArrayList<Integer> trips = (ArrayList<Integer>) map.get("Trips");
+ EntitySet set = getEntitySet("Trip");
+
+ EntitySetImpl result = new EntitySetImpl();
+ int i = 0;
+ if (trips != null) {
+ for (int trip : trips) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("TripId").getValue().equals(trip)) {
+ result.getEntities().add(e);
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ result.setCount(i);
+ return result;
+ }
+
+ private Entity getPhoto(String userName) {
+ Map<String, Object> map = this.peopleLinks.get(userName);
+ if (map == null) {
+ return null;
+ }
+
+ Integer photoID = (Integer) map.get("Photo");
+ EntitySet set = getEntitySet("Photos");
+ if (photoID != null) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("Id").getValue().equals(photoID.longValue())) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ private EntitySet getPlanItems(int tripId, EntitySetImpl result) {
+ getFlights(tripId, result);
+ getEvents(tripId, result);
+ return result;
+ }
+
+ private EntitySet getEvents(int tripId, EntitySetImpl result) {
+ Map<Integer, Object> map = this.tripLinks.get(tripId);
+ if (map == null) {
+ return null;
+ }
+
+ ArrayList<Integer> events = (ArrayList<Integer>) map.get("Events");
+ EntitySet set = getEntitySet("Event");
+ int i = result.getEntities().size();
+ if (events != null) {
+ for (int event : events) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("PlanItemId").getValue().equals(event)) {
+ result.getEntities().add(e);
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ result.setCount(i);
+ return result;
+ }
+
+ private EntitySet getFlights(int tripId, EntitySetImpl result) {
+ Map<Integer, Object> map = this.tripLinks.get(tripId);
+ if (map == null) {
+ return null;
+ }
+
+ ArrayList<Integer> flights = (ArrayList<Integer>) map.get("Flights");
+ EntitySet set = getEntitySet("Flight");
+ int i = result.getEntities().size();
+ if (flights != null) {
+ for (int flight : flights) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("PlanItemId").getValue().equals(flight)) {
+ result.getEntities().add(e);
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ result.setCount(i);
+ return result;
+ }
+
+ private EntitySet getTripPhotos(int tripId) {
+ Map<Integer, Object> map = this.tripLinks.get(tripId);
+ if (map == null) {
+ return null;
+ }
+
+ ArrayList<Integer> photos = (ArrayList<Integer>) map.get("Photos");
+
+ EntitySet set = getEntitySet("Photos");
+ EntitySetImpl result = new EntitySetImpl();
+ int i = 0;
+ if (photos != null) {
+ for (int photo : photos) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("Id").getValue().equals(photo)) {
+ result.getEntities().add(e);
+ i++;
+ break;
+ }
+ }
+ }
+ }
+ result.setCount(i);
+ return result;
+ }
+
+ private Entity getFlightFrom(int flighID) {
+ Map<String, Object> map = this.flightLinks.get(flighID);
+ if (map == null) {
+ return null;
+ }
+
+ String from = (String) map.get("From");
+ EntitySet set = getEntitySet("Airports");
+
+ if (from != null) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("IataCode").getValue().equals(from)) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Entity getFlightTo(int flighID) {
+ Map<String, Object> map = this.flightLinks.get(flighID);
+ if (map == null) {
+ return null;
+ }
+
+ String to = (String) map.get("To");
+ EntitySet set = getEntitySet("Airports");
+
+ if (to != null) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("IataCode").getValue().equals(to)) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Entity getFlightAirline(int flighID) {
+ Map<String, Object> map = this.flightLinks.get(flighID);
+ if (map == null) {
+ return null;
+ }
+
+ String airline = (String) map.get("Airline");
+ EntitySet set = getEntitySet("Airlines");
+
+ if (airline != null) {
+ for (Entity e : set.getEntities()) {
+ if (e.getProperty("AirlineCode").getValue().equals(airline)) {
+ return e;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void addNavigationLink(String navigation, Entity parentEntity, Entity childEntity) {
+
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(parentEntity.getType()));
+ String key = type.getKeyPredicateNames().get(0);
+ if (type.getName().equals("Person") && navigation.equals("Friends")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.peopleLinks.put((String) parentEntity.getProperty(key).getValue(), map);
+ }
+
+ ArrayList<String> friends = (ArrayList<String>) map.get("Friends");
+ if (friends == null) {
+ friends = new ArrayList<String>();
+ map.put("Friends", friends);
+ }
+ friends.add((String) childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Person") && navigation.equals("Trips")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.peopleLinks.put((String) parentEntity.getProperty(key).getValue(), map);
+ }
+
+ ArrayList<Integer> trips = (ArrayList<Integer>) map.get("Trips");
+ if (trips == null) {
+ trips = new ArrayList<Integer>();
+ map.put("Trips", trips);
+ }
+ trips.add((Integer) childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Person") && navigation.equals("Photo")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.peopleLinks.put((String) parentEntity.getProperty(key).getValue(), map);
+ }
+ map.put("Photo", childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Trip") && navigation.equals("PlanItems")) {
+ Map map = this.tripLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.tripLinks.put((Integer) parentEntity.getProperty(key).getValue(), map);
+ }
+ if (childEntity.getType().equals("Flight")) {
+ ArrayList<Integer> flights = (ArrayList<Integer>) map.get("Flights");
+ if (flights == null) {
+ flights = new ArrayList<Integer>();
+ map.put("Flights", flights);
+ }
+ flights.add((Integer) childEntity.getProperty(key).getValue());
+ } else {
+ ArrayList<Integer> events = (ArrayList<Integer>) map.get("Events");
+ if (events == null) {
+ events = new ArrayList<Integer>();
+ map.put("Events", events);
+ }
+ events.add((Integer) childEntity.getProperty(key).getValue());
+ }
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Trip") && navigation.equals("Photo")) {
+ Map map = this.tripLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.tripLinks.put((Integer) parentEntity.getProperty(key).getValue(), map);
+ }
+ ArrayList<Integer> photos = (ArrayList<Integer>) map.get("Photos");
+ if (photos == null) {
+ photos = new ArrayList<Integer>();
+ map.put("Photos", photos);
+ }
+ photos.add((Integer) childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Flight") && navigation.equals("From")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.flightLinks.put((Integer) parentEntity.getProperty(key).getValue(), map);
+ }
+ map.put("From", childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Flight") && navigation.equals("To")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.flightLinks.put((Integer) parentEntity.getProperty(key).getValue(), map);
+ }
+ map.put("To", childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else if (type.getName().equals("Flight") && navigation.equals("Airline")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map == null) {
+ map = new HashMap();
+ this.flightLinks.put((Integer) parentEntity.getProperty(key).getValue(), map);
+ }
+ map.put("Airline", childEntity.getProperty(key).getValue());
+ setLink(parentEntity, navigation, childEntity);
+ } else {
+ throw new RuntimeException("unknown relation");
+ }
+ }
+
+ protected static void setLink(Entity entity, final String navigationPropertyName,
+ final Entity target) {
+ Link link = new LinkImpl();
+ link.setTitle(navigationPropertyName);
+ link.setInlineEntity(target);
+ entity.getNavigationLinks().add(link);
+ }
+
+ public boolean updateNavigationLink(String navigationProperty, Entity parentEntity,
+ Entity updateEntity) {
+ boolean updated = false;
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(parentEntity.getType()));
+ String key = type.getKeyPredicateNames().get(0);
+
+ EdmEntityType updateType = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(updateEntity.getType()));
+ String updateKey = updateType.getKeyPredicateNames().get(0);
+
+ if (type.getName().equals("Person") && navigationProperty.equals("Photo")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.put("Photo", ((Long) updateEntity.getProperty(updateKey).getValue()).intValue());
+ updated = true;
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("From")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.put("From", updateEntity.getProperty(updateKey).getValue());
+ updated = true;
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("To")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.put("To", updateEntity.getProperty(updateKey).getValue());
+ updated = true;
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("Airline")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.put("Airline", updateEntity.getProperty(updateKey).getValue());
+ updated = true;
+ }
+ } else {
+ throw new RuntimeException("unknown relation");
+ }
+ return updated;
+ }
+
+ public Entity createEntity(String entitySetName, Entity entity, String location)
+ throws ODataApplicationException {
+
+ EntitySet set = this.entitySetMap.get(entitySetName);
+ EntityImpl copy = new EntityImpl();
+ copy.setType(entity.getType());
+ for (Property p : entity.getProperties()) {
+ copy.addProperty(p);
+ }
+
+ try {
+ copy.setId(new URI(location));
+ copy.setETag(UUID.randomUUID().toString());
+ } catch (URISyntaxException e) {
+ throw new ODataApplicationException("Failed to create ID for entity", 500,
+ Locale.getDefault());
+ }
+
+ set.getEntities().add(copy);
+ return copy;
+ }
+
+ public boolean deleteEntity(String entitySetName, String eTag, String key, Object keyValue) {
+ EntitySet set = getEntitySet(entitySetName);
+ Iterator<Entity> it = set.getEntities().iterator();
+ boolean removed = false;
+ while (it.hasNext()) {
+ Entity entity = it.next();
+ if (entity.getProperty(key).getValue().equals(keyValue) && eTag.equals("*")
+ || eTag.equals(entity.getETag())) {
+ it.remove();
+ removed = true;
+ break;
+ }
+ }
+ return removed;
+ }
+
+ public boolean updateProperty(String entitySetName, String eTag, String key, Object keyValue,
+ Property property) {
+ EntitySet set = getEntitySet(entitySetName);
+ Iterator<Entity> it = set.getEntities().iterator();
+ boolean replaced = false;
+ while (it.hasNext()) {
+ Entity entity = it.next();
+ if (entity.getProperty(key).getValue().equals(keyValue) && eTag.equals("*")
+ || eTag.equals(entity.getETag())) {
+ entity.getProperty(property.getName()).setValue(property.getValueType(),
+ property.getValue());
+ replaced = true;
+ break;
+ }
+ }
+ return replaced;
+ }
+
+ public EntitySet getNavigableEntitySet(Entity parentEntity, UriResourceNavigation navigation) {
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(parentEntity.getType()));
+
+ String key = type.getKeyPredicateNames().get(0);
+ String linkName = navigation.getProperty().getName();
+
+ EntitySet results = null;
+ if (type.getName().equals("Person") && linkName.equals("Friends")) {
+ results = getFriends((String) parentEntity.getProperty(key).getValue());
+ } else if (type.getName().equals("Person") && linkName.equals("Trips")) {
+ results = getTrips((String) parentEntity.getProperty(key).getValue());
+ } else if (type.getName().equals("Trip") && linkName.equals("PlanItems")) {
+ EntitySetImpl planitems = new EntitySetImpl();
+ if (navigation.getTypeFilterOnCollection() == null) {
+ results = getPlanItems((Integer) parentEntity.getProperty(key).getValue(), planitems);
+ } else if (navigation.getTypeFilterOnCollection().getName().equals("Flight")) {
+ results = getFlights((Integer) parentEntity.getProperty(key).getValue(), planitems);
+ } else if (navigation.getTypeFilterOnCollection().getName().equals("Event")) {
+ results = getEvents((Integer) parentEntity.getProperty(key).getValue(), planitems);
+ } else {
+ throw new RuntimeException("unknown relation");
+ }
+ } else if (type.getName().equals("Trip") && linkName.equals("Photos")) {
+ results = getTripPhotos((Integer) parentEntity.getProperty(key).getValue());
+ }
+ return results;
+ }
+
+ public Entity getNavigableEntity(Entity parentEntity, UriResourceNavigation navigation)
+ throws ODataApplicationException {
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(parentEntity.getType()));
+
+ String key = type.getKeyPredicateNames().get(0);
+ String linkName = navigation.getProperty().getName();
+
+ EntitySet results = null;
+ if (navigation.getProperty().isCollection()) {
+ results = getNavigableEntitySet(parentEntity, navigation);
+ return this.getEntity(results, navigation.getKeyPredicates());
+ }
+ if (type.getName().equals("Person") && linkName.equals("Photo")) {
+ return getPhoto((String) parentEntity.getProperty(key).getValue());
+ } else if (type.getName().equals("Flight") && linkName.equals("From")) {
+ return getFlightFrom((Integer) parentEntity.getProperty(key).getValue());
+ } else if (type.getName().equals("Flight") && linkName.equals("To")) {
+ return getFlightTo((Integer) parentEntity.getProperty(key).getValue());
+ } else if (type.getName().equals("Flight") && linkName.equals("Airline")) {
+ return getFlightAirline((Integer) parentEntity.getProperty(key).getValue());
+ } else {
+ throw new RuntimeException("unknown relation");
+ }
+ }
+
+ public boolean removeNavigationLink(String navigationProperty, Entity parentEntity,
+ Entity deleteEntity) {
+ boolean removed = false;
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(parentEntity.getType()));
+ String key = type.getKeyPredicateNames().get(0);
+
+ if (type.getName().equals("Person") && navigationProperty.equals("Friends")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ ArrayList<String> friends = (ArrayList<String>) map.get("Friends");
+ if (friends != null) {
+ friends.remove(deleteEntity.getProperty(key).getValue());
+ removed = true;
+ }
+ }
+ } else if (type.getName().equals("Person") && navigationProperty.equals("Trips")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ ArrayList<Integer> trips = (ArrayList<Integer>) map.get("Trips");
+ if (trips != null) {
+ trips.remove(deleteEntity.getProperty(key).getValue());
+ removed = true;
+ }
+ }
+ } else if (type.getName().equals("Person") && navigationProperty.equals("Photo")) {
+ Map map = this.peopleLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.remove("Photo");
+ removed = true;
+ }
+ } else if (type.getName().equals("Trip") && navigationProperty.equals("PlanItems")) {
+ Map map = this.tripLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ if (deleteEntity.getType().equals("Flight")) {
+ ArrayList<Integer> flights = (ArrayList<Integer>) map.get("Flights");
+ if (flights != null) {
+ flights.remove(deleteEntity.getProperty(key).getValue());
+ removed = true;
+ }
+ } else {
+ ArrayList<Integer> events = (ArrayList<Integer>) map.get("Events");
+ if (events != null) {
+ events.remove(deleteEntity.getProperty(key).getValue());
+ removed = true;
+ }
+ }
+ }
+ } else if (type.getName().equals("Trip") && navigationProperty.equals("Photo")) {
+ Map map = this.tripLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ ArrayList<Integer> photos = (ArrayList<Integer>) map.get("Photos");
+ if (photos != null) {
+ photos.remove(deleteEntity.getProperty(key).getValue());
+ removed = true;
+ }
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("From")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.remove("From");
+ removed = true;
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("To")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.remove("To");
+ removed = true;
+ }
+ } else if (type.getName().equals("Flight") && navigationProperty.equals("Airline")) {
+ Map map = this.flightLinks.get(parentEntity.getProperty(key).getValue());
+ if (map != null) {
+ map.remove("Airline");
+ removed = true;
+ }
+ } else {
+ throw new RuntimeException("unknown relation");
+ }
+ return removed;
+ }
+
+ // note these are not tied to entities for simplicity sake
+ public boolean updateMedia(Entity entity, InputStream mediaContent)
+ throws ODataApplicationException {
+ checkForMedia(entity);
+ return true;
+ }
+
+ // note these are not tied to entities for simplicity sake
+ public InputStream readMedia(Entity entity) throws ODataApplicationException {
+ checkForMedia(entity);
+ try {
+ return new FileInputStream(new File("src/test/resources/OlingoOrangeTM.png"));
+ } catch (FileNotFoundException e) {
+ throw new ODataApplicationException("image not found", 500, Locale.getDefault());
+ }
+ }
+
+ // note these are not tied to entities for simplicity sake
+ public boolean deleteMedia(Entity entity) throws ODataApplicationException {
+ checkForMedia(entity);
+ return true;
+ }
+
+ private void checkForMedia(Entity entity) throws ODataApplicationException {
+ EdmEntityType type = this.metadata.getEdm().getEntityType(
+ new FullQualifiedName(entity.getType()));
+ if (!type.hasStream()) {
+ throw new ODataApplicationException("No Media proeprty on the entity", 500,
+ Locale.getDefault());
+ }
+ }
+
+ public boolean deleteStream(Entity entity, EdmProperty property) {
+ // should remove stream links
+ return true;
+ }
+
+ public boolean updateStream(Entity entity, EdmProperty property, InputStream streamContent) {
+ // should add stream links
+ return true;
+ }
+}
\ No newline at end of file