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 2017/04/26 14:26:34 UTC

olingo-odata4 git commit: [OLINGO-1064] ComplexType is deserialized as Primitive Type if the value is NULL

Repository: olingo-odata4
Updated Branches:
  refs/heads/master 7e262c8d0 -> 272719d59


[OLINGO-1064] ComplexType is deserialized as Primitive Type if the value is NULL

Signed-off-by: Christian Amend <ch...@sap.com>


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

Branch: refs/heads/master
Commit: 272719d59fe84e7010b7c2117c1db0c31bfc0e00
Parents: 7e262c8
Author: i050510 <ra...@sap.com>
Authored: Tue Apr 25 14:05:30 2017 +0530
Committer: Christian Amend <ch...@sap.com>
Committed: Wed Apr 26 16:13:08 2017 +0200

----------------------------------------------------------------------
 .../olingo/fit/tecsvc/client/BasicITCase.java   | 110 +++++++++++++++++++
 ...AllPrimWithEmptyValueForComplexProperty.json |   7 ++
 ...pAllPrimWithNullValueForComplexProperty.json |   7 ++
 ...SCompAllPrimWithValueForComplexProperty.json |   7 ++
 .../ESTwoKeyNavWithNestedComplexTypes.json      |  38 +++++++
 .../core/serialization/ODataBinderImpl.java     |  63 ++++++-----
 6 files changed, 205 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
----------------------------------------------------------------------
diff --git a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
index 8cef37d..87dc3c3 100644
--- a/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
+++ b/fit/src/test/java/org/apache/olingo/fit/tecsvc/client/BasicITCase.java
@@ -29,6 +29,7 @@ import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.junit.Assume.assumeTrue;
 
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.net.URI;
 import java.util.Collections;
@@ -37,6 +38,7 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.olingo.client.api.EdmEnabledODataClient;
 import org.apache.olingo.client.api.ODataClient;
 import org.apache.olingo.client.api.communication.ODataClientErrorException;
 import org.apache.olingo.client.api.communication.request.cud.ODataDeleteRequest;
@@ -72,7 +74,9 @@ import org.apache.olingo.client.api.domain.ClientServiceDocument;
 import org.apache.olingo.client.api.domain.ClientValue;
 import org.apache.olingo.client.api.edm.xml.Reference;
 import org.apache.olingo.client.api.edm.xml.XMLMetadata;
+import org.apache.olingo.client.api.serialization.ODataDeserializerException;
 import org.apache.olingo.client.api.uri.URIBuilder;
+import org.apache.olingo.client.core.ODataClientFactory;
 import org.apache.olingo.client.core.uri.URIUtils;
 import org.apache.olingo.commons.api.edm.Edm;
 import org.apache.olingo.commons.api.edm.EdmActionImport;
@@ -108,6 +112,9 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
   private static final String ES_TWO_PRIM = "ESTwoPrim";
   private static final String ES_KEY_NAV = "ESKeyNav";
   private static final String ES_MIX_PRIM_COLL_COMP = "ESMixPrimCollComp";
+  private static final String PROPERTY_COMP_NAV = "CollPropertyCompNav";
+  private static final String COL_PROPERTY_COMP = "CollPropertyComp";
+  private static final String PROPERTY_COMP_TWO_PRIM = "PropertyCompTwoPrim";
 
   @Test
   public void readServiceDocument() {
@@ -1464,4 +1471,107 @@ public class BasicITCase extends AbstractParamTecSvcITCase {
 
     assertEquals(BigDecimal.valueOf(34), response.getBody().getPrimitiveValue().toValue());
   }
+  
+  
+  @Test
+  public void test1Olingo1064() throws ODataDeserializerException {
+    EdmMetadataRequest request = getClient().getRetrieveRequestFactory().getMetadataRequest(SERVICE_URI);
+    assertNotNull(request);
+    setCookieHeader(request);    
+    
+    ODataRetrieveResponse<Edm> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+    Edm edm = response.getBody();
+    
+    EdmEnabledODataClient odataClient = ODataClientFactory.getEdmEnabledClient(SERVICE_URI, edm, null);
+    final InputStream input = Thread.currentThread().getContextClassLoader().
+        getResourceAsStream("ESCompAllPrimWithValueForComplexProperty.json");
+    ClientEntity entity = odataClient.getReader().readEntity(input, ContentType.JSON);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertNotNull(entity.getProperty(PROPERTY_COMP).getComplexValue());
+    assertEquals("olingo.odata.test1.CTAllPrim", entity.getProperty(PROPERTY_COMP).getComplexValue().getTypeName());
+    assertEquals(PROPERTY_COMP, entity.getProperty(PROPERTY_COMP).getName());
+    assertNull(entity.getProperty(PROPERTY_COMP).getComplexValue().get("PropertyString").getPrimitiveValue());
+    assertNull(entity.getProperty(PROPERTY_COMP).getComplexValue().get("PropertyBoolean").getPrimitiveValue());
+  }
+  
+  @Test
+  public void test2Olingo1064() throws ODataDeserializerException {
+    EdmMetadataRequest request = getClient().getRetrieveRequestFactory().getMetadataRequest(SERVICE_URI);
+    assertNotNull(request);
+    setCookieHeader(request);    
+    
+    ODataRetrieveResponse<Edm> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+    Edm edm = response.getBody();
+    
+    EdmEnabledODataClient odataClient = ODataClientFactory.getEdmEnabledClient(SERVICE_URI, edm, null);
+    final InputStream input = Thread.currentThread().getContextClassLoader().
+        getResourceAsStream("ESCompAllPrimWithNullValueForComplexProperty.json");
+    ClientEntity entity = odataClient.getReader().readEntity(input, ContentType.JSON);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+    assertNotNull(entity.getProperty(PROPERTY_COMP).getComplexValue());
+    assertEquals("olingo.odata.test1.CTAllPrim", entity.getProperty(PROPERTY_COMP).getComplexValue().getTypeName());
+    assertEquals(PROPERTY_COMP, entity.getProperty(PROPERTY_COMP).getName());
+    assertNull(entity.getProperty(PROPERTY_COMP).getComplexValue().get(PROPERTY_COMP).getComplexValue());
+  }
+  
+  @Test
+  public void test3Olingo1064() throws ODataDeserializerException {
+    EdmMetadataRequest request = getClient().getRetrieveRequestFactory().getMetadataRequest(SERVICE_URI);
+    assertNotNull(request);
+    setCookieHeader(request);    
+    
+    ODataRetrieveResponse<Edm> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+    Edm edm = response.getBody();
+    
+    EdmEnabledODataClient odataClient = ODataClientFactory.getEdmEnabledClient(SERVICE_URI, edm, null);
+    final InputStream input = Thread.currentThread().getContextClassLoader().
+        getResourceAsStream("ESCompAllPrimWithEmptyValueForComplexProperty.json");
+    ClientEntity entity = odataClient.getReader().readEntity(input, ContentType.JSON);
+    assertEquals("olingo.odata.test1.CTAllPrim", entity.getProperty(PROPERTY_COMP).getComplexValue().getTypeName());
+    assertEquals(PROPERTY_COMP, entity.getProperty(PROPERTY_COMP).getName());
+    assertTrue(entity.getProperty(PROPERTY_COMP).getComplexValue().asJavaMap().size() == 0);
+  }
+  
+  @SuppressWarnings("unchecked")
+  @Test
+  public void test4Olingo1064() throws ODataDeserializerException {
+    EdmMetadataRequest request = getClient().getRetrieveRequestFactory().getMetadataRequest(SERVICE_URI);
+    assertNotNull(request);
+    setCookieHeader(request);    
+    
+    ODataRetrieveResponse<Edm> response = request.execute();
+    saveCookieHeader(response);
+    assertEquals(HttpStatusCode.OK.getStatusCode(), response.getStatusCode());
+
+    Edm edm = response.getBody();
+    
+    EdmEnabledODataClient odataClient = ODataClientFactory.getEdmEnabledClient(SERVICE_URI, edm, null);
+    final InputStream input = Thread.currentThread().getContextClassLoader().
+        getResourceAsStream("ESTwoKeyNavWithNestedComplexTypes.json");
+    ClientEntity entity = odataClient.getReader().readEntity(input, ContentType.JSON);
+    assertEquals("olingo.odata.test1.CTPrimComp", entity.getProperty(PROPERTY_COMP).getComplexValue().getTypeName());
+    assertEquals(PROPERTY_COMP, entity.getProperty(PROPERTY_COMP).getName());
+    Map<String, Object> map = entity.getProperty(PROPERTY_COMP).getComplexValue().asJavaMap();
+    assertEquals(map.size(), 2);
+    assertEquals(((Map<String, Object>)map.get(PROPERTY_COMP)).size(), 16);
+    assertNull(entity.getProperty(PROPERTY_COMP_NAV).getComplexValue().get(PROPERTY_COMP_NAV).getComplexValue());
+    assertEquals("Collection(olingo.odata.test1.CTPrimComp)", entity.getProperty(COL_PROPERTY_COMP).
+        getCollectionValue().getTypeName());
+    assertEquals(0, entity.getProperty(COL_PROPERTY_COMP).getCollectionValue().size());
+    assertEquals("olingo.odata.test1.CTNavFiveProp", entity.getProperty(PROPERTY_COMP_NAV).
+        getComplexValue().getTypeName());
+    assertEquals("olingo.odata.test1.CTTwoPrim", entity.getProperty(PROPERTY_COMP_TWO_PRIM).
+        getComplexValue().getTypeName());
+    assertNull(entity.getProperty(PROPERTY_COMP_TWO_PRIM).getComplexValue().
+        get(PROPERTY_COMP_TWO_PRIM).getComplexValue());
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/fit/src/test/resources/ESCompAllPrimWithEmptyValueForComplexProperty.json
----------------------------------------------------------------------
diff --git a/fit/src/test/resources/ESCompAllPrimWithEmptyValueForComplexProperty.json b/fit/src/test/resources/ESCompAllPrimWithEmptyValueForComplexProperty.json
new file mode 100644
index 0000000..45bfb75
--- /dev/null
+++ b/fit/src/test/resources/ESCompAllPrimWithEmptyValueForComplexProperty.json
@@ -0,0 +1,7 @@
+{
+  "@odata.context": "$metadata#ESCompAllPrim/$entity",
+  "@odata.metadataEtag": "W/\"2010a206-ee09-4cfb-9087-df530cdbb6ea\"",
+  "@odata.etag": "W/\"-32768\"",
+  "PropertyInt16": -32768,
+  "PropertyComp": {}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/fit/src/test/resources/ESCompAllPrimWithNullValueForComplexProperty.json
----------------------------------------------------------------------
diff --git a/fit/src/test/resources/ESCompAllPrimWithNullValueForComplexProperty.json b/fit/src/test/resources/ESCompAllPrimWithNullValueForComplexProperty.json
new file mode 100644
index 0000000..4d55e06
--- /dev/null
+++ b/fit/src/test/resources/ESCompAllPrimWithNullValueForComplexProperty.json
@@ -0,0 +1,7 @@
+{
+  "@odata.context": "$metadata#ESCompAllPrim/$entity",
+  "@odata.metadataEtag": "W/\"2010a206-ee09-4cfb-9087-df530cdbb6ea\"",
+  "@odata.etag": "W/\"-32768\"",
+  "PropertyInt16": -32768,
+  "PropertyComp": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/fit/src/test/resources/ESCompAllPrimWithValueForComplexProperty.json
----------------------------------------------------------------------
diff --git a/fit/src/test/resources/ESCompAllPrimWithValueForComplexProperty.json b/fit/src/test/resources/ESCompAllPrimWithValueForComplexProperty.json
new file mode 100644
index 0000000..9b09bd0
--- /dev/null
+++ b/fit/src/test/resources/ESCompAllPrimWithValueForComplexProperty.json
@@ -0,0 +1,7 @@
+{
+  "@odata.context": "$metadata#ESCompAllPrim/$entity",
+  "@odata.metadataEtag": "W/\"2010a206-ee09-4cfb-9087-df530cdbb6ea\"",
+  "@odata.etag": "W/\"-32768\"",
+  "PropertyInt16": -32768,
+  "PropertyComp": { "PropertyString": null, "PropertyBoolean": null }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/fit/src/test/resources/ESTwoKeyNavWithNestedComplexTypes.json
----------------------------------------------------------------------
diff --git a/fit/src/test/resources/ESTwoKeyNavWithNestedComplexTypes.json b/fit/src/test/resources/ESTwoKeyNavWithNestedComplexTypes.json
new file mode 100644
index 0000000..679594d
--- /dev/null
+++ b/fit/src/test/resources/ESTwoKeyNavWithNestedComplexTypes.json
@@ -0,0 +1,38 @@
+{
+  "@odata.context": "../$metadata#ESTwoKeyNav",
+  "@odata.metadataEtag": "W/\"e5db7a43-370a-44d7-9600-9f0443e6e351\"",
+  "PropertyInt16": 1,
+  "PropertyString": "2",
+  "PropertyComp": {
+	"PropertyInt16": 11,
+	"PropertyComp": {
+	  "PropertyString": "StringValue",
+	  "PropertyBinary": "ASNFZ4mrze8=",
+	  "PropertyBoolean": true,
+	  "PropertyByte": 255,
+	  "PropertyDate": "2012-12-03",
+	  "PropertyDateTimeOffset": null,
+	  "PropertyDecimal": 34,
+	  "PropertySingle": 17900000,
+	  "PropertyDouble": -17900000,
+	  "PropertyDuration": "PT6S",
+	  "PropertyGuid": "01234567-89ab-cdef-0123-456789abcdef",
+	  "PropertyInt16": 32767,
+	  "PropertyInt32": 2147483647,
+	  "PropertyInt64": 9223372036854775807,
+	  "PropertySByte": 127,
+	  "PropertyTimeOfDay": "21:05:59"
+	}
+  },
+  "PropertyCompNav": {
+	"PropertyInt16": 1,
+	"PropertyComp": null
+  },
+  "CollPropertyComp": [],
+  "CollPropertyCompNav": null,
+  "CollPropertyString": [
+	"1",
+	"2"
+  ],
+  "PropertyCompTwoPrim": null
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/272719d5/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
----------------------------------------------------------------------
diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
index 1059c58..77764a5 100644
--- a/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
+++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/serialization/ODataBinderImpl.java
@@ -470,7 +470,7 @@ public class ODataBinderImpl implements ODataBinder {
             URIUtils.getURI(base, href), title, metadataETag));
       }
     }
-
+    
     for (ClientLink link : odataLinked.getNavigationLinks()) {
       if (!(link instanceof ClientInlineEntity) && !(link instanceof ClientInlineEntitySet)) {
         odataAnnotations(linked.getNavigationLink(link.getName()), link);
@@ -858,10 +858,10 @@ public class ODataBinderImpl implements ODataBinder {
         }
         lcValue.add(getODataProperty(edmPropertyType, property));
       }
-
+      
       odataNavigationLinks(edmType, valuable.asComplex(), lcValue, metadataETag, contextURL);
       odataAnnotations(valuable.asComplex(), lcValue);
-
+      
       value = lcValue;
     } else {
       if (valuable.isGeospatial()) {
@@ -874,31 +874,40 @@ public class ODataBinderImpl implements ODataBinder {
                 : EdmPrimitiveTypeKind.valueOfFQN(type.toString())).
             build();
       } else if (valuable.isPrimitive() || valuable.getValueType() == null) {
-        // fixes non-string values treated as string when no type information is available at de-serialization level
-        if (type != null && !EdmPrimitiveTypeKind.String.getFullQualifiedName().equals(type)
-            && EdmPrimitiveType.EDM_NAMESPACE.equals(type.getNamespace())
-            && valuable.asPrimitive() instanceof String) {
-
-          final EdmPrimitiveType primitiveType =
-              EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.valueOf(type.getName()));
-          final Class<?> returnType = primitiveType.getDefaultType().isAssignableFrom(Calendar.class)
-              ? Timestamp.class : primitiveType.getDefaultType();
-          try {
-            valuable.setValue(valuable.getValueType(),
-                primitiveType.valueOfString(valuable.asPrimitive().toString(),
-                    null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null,
-                    returnType));
-          } catch (EdmPrimitiveTypeException e) {
-            throw new IllegalArgumentException(e);
-          }
+     // fixes non-string values treated as string when no type information is available at de-serialization level
+        Edm edm = null;
+        if (client instanceof EdmEnabledODataClient && type != null) {
+          edm = ((EdmEnabledODataClient) client).getEdm(metadataETag);
         }
-
-        value = client.getObjectFactory().newPrimitiveValueBuilder().
-            setValue(valuable.asPrimitive()).
-            setType(type == null || !EdmPrimitiveType.EDM_NAMESPACE.equals(type.getNamespace())
-                ? null
-                : EdmPrimitiveTypeKind.valueOfFQN(type.toString())).
-            build();
+        if (edm != null && edm.getComplexType(type) != null) {
+          ClientComplexValue cValue = client.getObjectFactory().newComplexValue(type.toString());
+          cValue.add(new ClientPropertyImpl(((Property)valuable).getName(), null));
+          value = cValue;
+          } else {
+            if (type != null && !EdmPrimitiveTypeKind.String.getFullQualifiedName().equals(type)
+              && EdmPrimitiveType.EDM_NAMESPACE.equals(type.getNamespace())
+              && valuable.asPrimitive() instanceof String) {
+  
+            final EdmPrimitiveType primitiveType =
+                EdmPrimitiveTypeFactory.getInstance(EdmPrimitiveTypeKind.valueOf(type.getName()));
+            final Class<?> returnType = primitiveType.getDefaultType().isAssignableFrom(Calendar.class)
+                ? Timestamp.class : primitiveType.getDefaultType();
+            try {
+              valuable.setValue(valuable.getValueType(),
+                  primitiveType.valueOfString(valuable.asPrimitive().toString(),
+                      null, null, Constants.DEFAULT_PRECISION, Constants.DEFAULT_SCALE, null,
+                      returnType));
+            } catch (EdmPrimitiveTypeException e) {
+              throw new IllegalArgumentException(e);
+            }
+          }
+          value = client.getObjectFactory().newPrimitiveValueBuilder().
+              setValue(valuable.asPrimitive()).
+              setType(type == null || !EdmPrimitiveType.EDM_NAMESPACE.equals(type.getNamespace())
+                  ? null
+                  : EdmPrimitiveTypeKind.valueOfFQN(type.toString())).
+              build();
+          }
       } else if (valuable.isComplex()) {
         final ClientComplexValue cValue =
             client.getObjectFactory().newComplexValue(type == null ? null : type.toString());