You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by mi...@apache.org on 2014/07/01 16:21:59 UTC

git commit: [OLINGO-317] Added complex type handling

Repository: olingo-odata4
Updated Branches:
  refs/heads/Olingo-317_DeSerializerRefactoring 839e96045 -> 71bdaed30


[OLINGO-317] Added complex type handling


Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo
Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/71bdaed3
Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/71bdaed3
Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/71bdaed3

Branch: refs/heads/Olingo-317_DeSerializerRefactoring
Commit: 71bdaed3003a6c903888a3465c9a338703596138
Parents: 839e960
Author: Michael Bolz <mi...@sap.com>
Authored: Tue Jul 1 13:11:36 2014 +0200
Committer: Michael Bolz <mi...@sap.com>
Committed: Tue Jul 1 16:21:42 2014 +0200

----------------------------------------------------------------------
 .../serializer/json/ODataJsonSerializer.java    | 107 +++++++++----------
 .../json/ODataJsonSerializerTest.java           |  61 ++++++-----
 .../tecsvc/processor/SampleJsonProcessor.java   |  82 +++++++++++---
 3 files changed, 151 insertions(+), 99 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/71bdaed3/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
index 8cb5f0c..c3fe720 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializer.java
@@ -18,36 +18,24 @@
  */
 package org.apache.olingo.server.core.serializer.json;
 
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStreamWriter;
-import java.util.List;
-
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.ODataRuntimeException;
-import org.apache.olingo.commons.api.data.ContextURL;
-import org.apache.olingo.commons.api.data.Entity;
-import org.apache.olingo.commons.api.data.EntitySet;
-import org.apache.olingo.commons.api.data.LinkedComplexValue;
-import org.apache.olingo.commons.api.data.Property;
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmComplexType;
-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.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.data.*;
+import org.apache.olingo.commons.api.edm.*;
 import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.core.serializer.utils.CircleStreamBuffer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.fasterxml.jackson.core.JsonFactory;
-import com.fasterxml.jackson.core.JsonGenerator;
-import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.List;
 
 public class ODataJsonSerializer implements ODataSerializer {
 
@@ -148,38 +136,14 @@ public class ODataJsonSerializer implements ODataSerializer {
       }
     } else {
       if (edmProperty.isPrimitive()) {
-        if (property.isPrimitive()) {
-          writePrimitiveValue(edmProperty, property.asPrimitive(), json);
-        } else if (property.isGeospatial()) {
-          throw new ODataRuntimeException("Property type not yet supported!");
-        } else if (property.isEnum()) {
-          json.writeString(property.asEnum().toString());
-        } else {
-          throw new ODataRuntimeException("Inconsistent property type!");
-        }
+        handlePrimitive(edmProperty, property, json);
       } else if (edmProperty.isCollection()) {
-        json.writeStartArray();
-        for (Object value : property.asCollection()) {
-          switch (property.getValueType()) {
-          case COLLECTION_PRIMITIVE:
-            writePrimitiveValue(edmProperty, value, json);
-            break;
-          case COLLECTION_GEOSPATIAL:
-            throw new ODataRuntimeException("Property type not yet supported!");
-          case COLLECTION_ENUM:
-            json.writeString(value.toString());
-            break;
-          case COLLECTION_LINKED_COMPLEX:
-            writeLinkedComplexValue(edmProperty, (LinkedComplexValue) value, json);
-            break;
-          default:
-            throw new ODataRuntimeException("Property type not yet supported!");
-          }
-        }
-        json.writeEndArray();
+        handleCollection(edmProperty, property, json);
       } else {
         if (property.isLinkedComplex()) {
-          writeLinkedComplexValue(edmProperty, property.asLinkedComplex(), json);
+          writeComplexValue(edmProperty, property.asLinkedComplex().getValue(), json);
+        } else if(property.isComplex()) {
+          writeComplexValue(edmProperty, property.asComplex(), json);
         } else {
           throw new ODataRuntimeException("Property type not yet supported!");
         }
@@ -187,6 +151,42 @@ public class ODataJsonSerializer implements ODataSerializer {
     }
   }
 
+  private void handleCollection(EdmProperty edmProperty, Property property, JsonGenerator json)
+          throws IOException, EdmPrimitiveTypeException {
+    json.writeStartArray();
+    for (Object value : property.asCollection()) {
+      switch (property.getValueType()) {
+      case COLLECTION_PRIMITIVE:
+        writePrimitiveValue(edmProperty, value, json);
+        break;
+      case COLLECTION_GEOSPATIAL:
+        throw new ODataRuntimeException("Property type not yet supported!");
+      case COLLECTION_ENUM:
+        json.writeString(value.toString());
+        break;
+      case COLLECTION_LINKED_COMPLEX:
+        writeComplexValue(edmProperty, ((LinkedComplexValue) value).getValue(), json);
+        break;
+      default:
+        throw new ODataRuntimeException("Property type not yet supported!");
+      }
+    }
+    json.writeEndArray();
+  }
+
+  private void handlePrimitive(EdmProperty edmProperty, Property property, JsonGenerator json)
+          throws EdmPrimitiveTypeException, IOException {
+    if (property.isPrimitive()) {
+      writePrimitiveValue(edmProperty, property.asPrimitive(), json);
+    } else if (property.isGeospatial()) {
+      throw new ODataRuntimeException("Property type not yet supported!");
+    } else if (property.isEnum()) {
+      json.writeString(property.asEnum().toString());
+    } else {
+      throw new ODataRuntimeException("Inconsistent property type!");
+    }
+  }
+
   protected void writePrimitiveValue(final EdmProperty edmProperty, final Object primitiveValue, JsonGenerator json)
       throws EdmPrimitiveTypeException, IOException {
     final EdmPrimitiveType type = (EdmPrimitiveType) edmProperty.getType();
@@ -209,10 +209,9 @@ public class ODataJsonSerializer implements ODataSerializer {
     }
   }
 
-  private void writeLinkedComplexValue(final EdmProperty edmProperty, final LinkedComplexValue linkedComplexValue,
-      JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
+  private void writeComplexValue(final EdmProperty edmProperty, final List<Property> properties,
+                                       JsonGenerator json) throws IOException, EdmPrimitiveTypeException {
     final EdmComplexType type = (EdmComplexType) edmProperty.getType();
-    final List<Property> properties = linkedComplexValue.getValue();
     json.writeStartObject();
     for (final String propertyName : type.getPropertyNames()) {
       final Property property = findProperty(propertyName, properties);

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/71bdaed3/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
index 1008c5f..e7563b0 100644
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
+++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java
@@ -18,15 +18,10 @@
  */
 package org.apache.olingo.server.core.serializer.json;
 
-import org.apache.olingo.commons.api.ODataRuntimeException;
 import org.apache.olingo.commons.api.data.ContextURL;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.ValueType;
-import org.apache.olingo.commons.api.edm.EdmEntitySet;
-import org.apache.olingo.commons.api.edm.EdmEntityType;
-import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
-import org.apache.olingo.commons.api.edm.EdmProperty;
-import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.*;
 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;
@@ -36,17 +31,11 @@ import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.mockito.Mockito;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.List;
-import java.util.UUID;
+import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -65,11 +54,14 @@ public class ODataJsonSerializerTest {
 
   public static class TecComplexProperty implements TechProperty {
 
-    final String name;
     final String typeName;
-    public TecComplexProperty(String typeName, String name) {
-      this.name = name;
+    final String name;
+    final List<EdmProperty> properties;
+
+    public TecComplexProperty(String typeName, String name, List<EdmProperty> propertyNames) {
       this.typeName = typeName;
+      this.name = name;
+      this.properties = new ArrayList<EdmProperty>(propertyNames);
     }
     @Override
     public String getName() {
@@ -83,6 +75,9 @@ public class ODataJsonSerializerTest {
     public EdmPrimitiveTypeKind getType() {
       return null;
     }
+    public List<EdmProperty> getProperties() {
+      return properties;
+    }
   }
 
   enum TecSimpleProperty implements TechProperty {
@@ -181,7 +176,7 @@ public class ODataJsonSerializerTest {
     Mockito.when(edmETCompAllPrim.getName()).thenReturn(ETCompAllPrim);
     List<EdmProperty> capProperties = Arrays.asList(
         mockProperty(TecSimpleProperty.Int16, false),
-        mockProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim), false, true)
+        mockProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim, properties), false)
     );
     List<String> capPropertyNames = new ArrayList<String>();
 
@@ -193,22 +188,27 @@ public class ODataJsonSerializerTest {
   }
 
   private EdmProperty mockProperty(TechProperty name) {
-    return mockProperty(name, true, false);
+    return mockProperty(name, true);
   }
 
-  private EdmProperty mockProperty(TechProperty name, boolean nullable) {
-    return mockProperty(name, nullable, false);
-  }
-
-  private EdmProperty mockProperty(TechProperty tecProperty, boolean nullable, boolean complex) {
+  private EdmProperty mockProperty(TechProperty tecProperty, boolean nullable) {
     EdmProperty edmElement = Mockito.mock(EdmProperty.class);
     Mockito.when(edmElement.getName()).thenReturn(tecProperty.getName());
-    if(complex) {
+    if (tecProperty instanceof TecComplexProperty) {
+      TecComplexProperty complexProperty = (TecComplexProperty) tecProperty;
       Mockito.when(edmElement.isPrimitive()).thenReturn(false);
-      EdmType type = Mockito.mock(EdmType.class);
+      EdmComplexType type = Mockito.mock(EdmComplexType.class);
       Mockito.when(type.getKind()).thenReturn(EdmTypeKind.COMPLEX);
       Mockito.when(type.getName()).thenReturn(tecProperty.getTypeName());
       Mockito.when(edmElement.getType()).thenReturn(type);
+
+      List<String> propertyNames = new ArrayList<String>();
+      List<EdmProperty> properties = complexProperty.getProperties();
+      for (EdmProperty property : properties) {
+        propertyNames.add(property.getName());
+        Mockito.when(type.getProperty(property.getName())).thenReturn(property);
+      }
+      Mockito.when(type.getPropertyNames()).thenReturn(propertyNames);
     } else {
       Mockito.when(edmElement.isPrimitive()).thenReturn(true);
       // TODO: set default values
@@ -287,20 +287,23 @@ public class ODataJsonSerializerTest {
     Assert.assertEquals(100, count);
   }
 
-  @Test(expected = ODataRuntimeException.class)
+  @Test
   public void entityETCompAllPrim() throws Exception {
     Entity complexCtAllPrim = createETAllPrim();
 
     Entity entity = new EntityImpl();
     entity.addProperty(new PropertyImpl("Edm.Int16", TecSimpleProperty.Int16.name, ValueType.PRIMITIVE, 4711));
-    entity.addProperty(createProperty(new TecComplexProperty(CTAllPrim_Type, CTAllPrim),
-        ValueType.COMPLEX, complexCtAllPrim));
+    entity.addProperty(createProperty(
+            new TecComplexProperty(CTAllPrim_Type, CTAllPrim, Collections.<EdmProperty>emptyList()),
+            ValueType.COMPLEX, complexCtAllPrim.getProperties()));
 
     InputStream result = serializer.entity(edmETCompAllPrim, entity, contextUrl);
     String resultString = streamToString(result);
     String expectedResult = "{" +
         "\"@odata.context\":\"http://localhost:8080/test.svc\"," +
         "\"PropertyInt16\":4711," +
+        "\"CTAllPrim\":{" +
+        "\"PropertyInt16\":4711," +
         "\"PropertyString\":\"StringValue\"," +
         "\"PropertyBoolean\":true," +
         "\"PropertyByte\":19," +
@@ -316,7 +319,7 @@ public class ODataJsonSerializerTest {
         "\"PropertyDuration\":\"P16148383DT8H0S\"," +
         "\"PropertyGuid\":\"0000aaaa-00bb-00cc-00dd-000000ffffff\"," +
         "\"PropertyTimeOfDay\":\"10:12:00\"" +
-        "}";
+        "}}";
     Assert.assertEquals(expectedResult, resultString);
   }
 

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/71bdaed3/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/SampleJsonProcessor.java
----------------------------------------------------------------------
diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/SampleJsonProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/SampleJsonProcessor.java
index 8cf00e9..cf40489 100644
--- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/SampleJsonProcessor.java
+++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/SampleJsonProcessor.java
@@ -19,6 +19,8 @@
 package org.apache.olingo.server.tecsvc.processor;
 
 import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.UUID;
 
 import org.apache.olingo.commons.api.data.ContextURL;
@@ -27,7 +29,10 @@ import org.apache.olingo.commons.api.data.EntitySet;
 import org.apache.olingo.commons.api.data.Property;
 import org.apache.olingo.commons.api.data.ValueType;
 import org.apache.olingo.commons.api.edm.Edm;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
 import org.apache.olingo.commons.api.format.ContentType;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.commons.api.http.HttpStatusCode;
@@ -41,6 +46,7 @@ import org.apache.olingo.server.api.processor.EntityProcessor;
 import org.apache.olingo.server.api.processor.EntitySetProcessor;
 import org.apache.olingo.server.api.serializer.ODataSerializer;
 import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriResource;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -60,16 +66,13 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
     public void readEntitySet(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) {
       long time = System.nanoTime();
 
-      EntitySet entitySet = createEntitySet();
-
       LOG.info((System.nanoTime() - time) / 1000 + " microseconds");
       time = System.nanoTime();
       ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
-      response.setContent(serializer.entitySet(
-              edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
-                      .getEntitySet("ESAllPrim"),
-              entitySet,
-              ContextURL.getInstance(URI.create("dummyContextURL"))));
+      EdmEntitySet edmEntitySet = getEntitySet(uriInfo);
+      EntitySet entitySet = createEntitySet(edmEntitySet.getEntityType());
+      response.setContent(serializer.entitySet(edmEntitySet, entitySet,
+              getContextUrl(request, edmEntitySet.getEntityType())));
       LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
 
       response.setStatusCode(HttpStatusCode.OK.getStatusCode());
@@ -79,23 +82,45 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
     @Override
     public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, String format) {
       long time = System.nanoTime();
-      Entity entity = createEntity();
 
       LOG.info((System.nanoTime() - time) / 1000 + " microseconds");
       time = System.nanoTime();
       ODataSerializer serializer = odata.createSerializer(ODataFormat.JSON);
-      response.setContent(serializer.entity(
-              edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
-                      .getEntitySet("ESAllPrim").getEntityType(),
-              entity,
-              ContextURL.getInstance(URI.create("dummyContextURL"))));
+      EdmEntityType entityType = getEntityType(uriInfo);
+      Entity entity = createEntity(entityType);
+
+      response.setContent(serializer.entity(entityType, entity,
+              getContextUrl(request, entityType)));
       LOG.info("Finished in " + (System.nanoTime() - time) / 1000 + " microseconds");
 
       response.setStatusCode(HttpStatusCode.OK.getStatusCode());
       response.setHeader("Content-Type", ContentType.APPLICATION_JSON.toContentTypeString());
     }
 
-    protected Entity createEntity() {
+  private ContextURL getContextUrl(ODataRequest request, EdmEntityType entityType) {
+    return ContextURL.getInstance(URI.create(request.getRawBaseUri() + "/" + entityType.getName()));
+  }
+
+  public EdmEntityType getEntityType(UriInfo uriInfo) {
+    return getEntitySet(uriInfo).getEntityType();
+  }
+
+  public EdmEntitySet getEntitySet(UriInfo uriInfo) {
+      List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+      if(resourcePaths.isEmpty()) {
+        throw new RuntimeException("Invalid resource path.");
+      }
+      String entitySetName = resourcePaths.get(resourcePaths.size()-1).toString();
+      return edm.getEntityContainer(new FullQualifiedName("com.sap.odata.test1", "Container"))
+              .getEntitySet(entitySetName);
+    }
+
+    protected Entity createEntity(EdmEntityType entityType) {
+      boolean complex = (entityType.getName().contains("Comp"));
+      return createEntity(complex);
+    }
+
+    protected Entity createEntity(boolean complex) {
       Entity entity = new EntityImpl();
       Property property = new PropertyImpl();
       property.setName("PropertyString");
@@ -109,15 +134,40 @@ public class SampleJsonProcessor implements EntitySetProcessor, EntityProcessor
       propertyGuid.setName("PropertyGuid");
       propertyGuid.setValue(ValueType.PRIMITIVE, UUID.randomUUID());
       entity.getProperties().add(propertyGuid);
+
+      if(complex) {
+        entity.addProperty(createComplexProperty());
+      }
+
       return entity;
     }
 
-    protected EntitySet createEntitySet() {
+  protected Property createComplexProperty() {
+    List<Property> properties = new ArrayList<Property>();
+    Property property = new PropertyImpl();
+    property.setName("PropertyString");
+    property.setValue(ValueType.PRIMITIVE, "dummyValue");
+    properties.add(property);
+    Property propertyInt = new PropertyImpl();
+    propertyInt.setName("PropertyInt16");
+    propertyInt.setValue(ValueType.PRIMITIVE, 42);
+    properties.add(propertyInt);
+    Property propertyGuid = new PropertyImpl();
+    propertyGuid.setName("PropertyGuid");
+    propertyGuid.setValue(ValueType.PRIMITIVE, UUID.randomUUID());
+    properties.add(propertyGuid);
+
+    return new PropertyImpl("com.sap.odata.test1.ETCompAllPrim", "PropertyComplex", ValueType.COMPLEX,
+            properties);
+  }
+
+
+  protected EntitySet createEntitySet(EdmEntityType edmEntityType) {
       EntitySet entitySet = new EntitySetImpl();
       entitySet.setCount(4242);
       entitySet.setNext(URI.create("nextLinkURI"));
       for (int i = 0; i < 1000; i++) {
-        entitySet.getEntities().add(createEntity());
+        entitySet.getEntities().add(createEntity(edmEntityType));
       }
       return entitySet;
     }