From b7d2c5f4416d0743ac4dfa878d3e2e187b208480 Mon Sep 17 00:00:00 2001 From: Christian Amend Date: Fri, 6 Feb 2015 14:12:23 +0100 Subject: [PATCH] [OLINGO-558] Introduce EdmMapping for deserialization --- .../olingo/commons/api/edm/EdmMappable.java | 4 +- .../olingo/commons/api/edm/EdmMapping.java | 29 +-- .../server/api/edm/provider/Mapping.java | 79 ++----- .../json/ODataJsonDeserializer.java | 41 +++- .../core/edm/provider/EdmMappingTest.java | 70 ++++++ .../json/ODataJsonDeserializerEntityTest.java | 222 +++++++++++------- 6 files changed, 264 insertions(+), 181 deletions(-) create mode 100644 lib/server-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmMappingTest.java diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMappable.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMappable.java index b4c0658ef..86b5b2196 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMappable.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMappable.java @@ -24,9 +24,9 @@ package org.apache.olingo.commons.api.edm; public interface EdmMappable { /** - * Get mapping information applied to an EDM element + * Get mapping information applied to an EDM element. May return null if no mapping is defined. * - * @return {@link EdmMapping} + * @return {@link EdmMapping} or null if no mapping is defined */ EdmMapping getMapping(); } diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMapping.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMapping.java index c66e83552..b116fd078 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMapping.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmMapping.java @@ -24,30 +24,9 @@ package org.apache.olingo.commons.api.edm; public interface EdmMapping { /** - * Get the mapping value - * - * @return mapping name as String + * The class which is returned here will be used to during deserialization to replace the default java class for a + * primitive type. + * @return class used during deserialization */ - String getInternalName(); - - /** - * Get the set object for this mapping - * - * @return {@link Object} object - */ - Object getObject(); - - /** - * Gets the key under which the resource source value can be found in the data map. - * - * @return the key of the media resource source - */ - String getMediaResourceSourceKey(); - - /** - * Gets the key under which the resource mime type can be found in the data map. - * - * @return the key of the media resource type - */ - String getMediaResourceMimeTypeKey(); + Class getMappedJavaClass(); } diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/edm/provider/Mapping.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/edm/provider/Mapping.java index 82a935a99..823c29d04 100644 --- a/lib/server-api/src/main/java/org/apache/olingo/server/api/edm/provider/Mapping.java +++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/edm/provider/Mapping.java @@ -19,78 +19,33 @@ package org.apache.olingo.server.api.edm.provider; import org.apache.olingo.commons.api.edm.EdmMapping; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +/** + * Content of this class does not appear within the CSDL metadata document. This class is used to perform server + * internal mapping for edm primitive types to java types. + */ public class Mapping implements EdmMapping { - private String value; - - private Object object; - - private String mediaResourceSourceKey; - - private String mediaResourceMimeTypeKey; - - @Override - public String getInternalName() { - return value; - } - - @Override - public Object getObject() { - return object; - } - - @Override - public String getMediaResourceSourceKey() { - return mediaResourceSourceKey; - } - - @Override - public String getMediaResourceMimeTypeKey() { - return mediaResourceMimeTypeKey; - } + private Class mappedJavaClass; /** - * Sets the value for this {@link Mapping}. - * - * @param value - * @return {@link Mapping} for method chaining + * Sets the class to be used during deserialization to transofrm an EDM primitive type into this java class. To see + * which classes work for which primitive type refer to {@link EdmPrimitiveType}. + * @param mappedJavaClass + * @return this for method chaining */ - public Mapping setInternalName(final String value) { - this.value = value; + public Mapping setMappedJavaClass(Class mappedJavaClass) { + this.mappedJavaClass = mappedJavaClass; return this; } - /** - * Sets an object. This method can be used by a provider to set whatever it wants to associate with this. - * - * @param object - * @return {@link Mapping} for method chaining + /* (non-Javadoc) + * @see org.apache.olingo.commons.api.edm.EdmMapping#getMappedJavaClass() */ - public Mapping setObject(final Object object) { - this.object = object; - return this; + @Override + public Class getMappedJavaClass() { + return mappedJavaClass; } - /** - * Sets the key for the resource source key which is used for the lookup in the data map - * - * @param mediaResourceSourceKey under which the source can be found in the data map - * @return {@link Mapping} for method chaining - */ - public Mapping setMediaResourceSourceKey(final String mediaResourceSourceKey) { - this.mediaResourceSourceKey = mediaResourceSourceKey; - return this; - } - - /** - * Sets the key for the resource mime type key which is used for the lookup in the data map - * - * @param mediaResourceMimeTypeKey under which the mime type can be found in the data map - * @return {@link Mapping} for method chaining - */ - public Mapping setMediaResourceMimeTypeKey(final String mediaResourceMimeTypeKey) { - this.mediaResourceMimeTypeKey = mediaResourceMimeTypeKey; - return this; - } } diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java index 6d032156b..7e624e36d 100644 --- a/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java +++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java @@ -315,7 +315,7 @@ public class ODataJsonDeserializer implements ODataDeserializer { } private Property consumePropertyNode(final EdmProperty edmProperty, final JsonNode jsonNode) - throws DeserializerException { + throws DeserializerException { Property property = new PropertyImpl(); property.setName(edmProperty.getName()); property.setType(edmProperty.getType().getFullQualifiedName().getFullQualifiedNameAsString()); @@ -355,7 +355,7 @@ public class ODataJsonDeserializer implements ODataDeserializer { } private Object readComplexNode(final EdmProperty edmProperty, final JsonNode jsonNode) - throws DeserializerException { + throws DeserializerException { // read and add all complex properties Object value = readComplexValue(edmProperty, jsonNode); @@ -373,7 +373,7 @@ public class ODataJsonDeserializer implements ODataDeserializer { } } // remove here to avoid iterator issues. - if(!jsonNode.isNull()) { + if (!jsonNode.isNull()) { ((ObjectNode) jsonNode).remove(toRemove); } // Afterwards the node must be empty @@ -431,7 +431,7 @@ public class ODataJsonDeserializer implements ODataDeserializer { } private Object readComplexValue(EdmProperty edmComplexProperty, JsonNode jsonNode) throws DeserializerException { - if(isValidNull(edmComplexProperty, jsonNode)) { + if (isValidNull(edmComplexProperty, jsonNode)) { return null; } if (jsonNode.isArray() || !jsonNode.isContainerNode()) { @@ -465,17 +465,18 @@ public class ODataJsonDeserializer implements ODataDeserializer { private Object readTypeDefinitionValue(EdmProperty edmProperty, JsonNode jsonNode) throws DeserializerException { checkForValueNode(edmProperty, jsonNode); - if(isValidNull(edmProperty, jsonNode)) { + if (isValidNull(edmProperty, jsonNode)) { return null; } try { EdmTypeDefinition edmTypeDefinition = (EdmTypeDefinition) edmProperty.getType(); checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmTypeDefinition.getUnderlyingType().getName(), jsonNode); + Class javaClass = getJavaClassForPrimitiveType(edmProperty, edmTypeDefinition.getUnderlyingType()); return edmTypeDefinition.valueOfString(jsonNode.asText(), edmProperty.isNullable(), edmTypeDefinition.getMaxLength(), edmTypeDefinition.getPrecision(), edmTypeDefinition.getScale(), edmTypeDefinition.isUnicode(), - edmTypeDefinition.getDefaultType()); + javaClass); } catch (EdmPrimitiveTypeException e) { throw new DeserializerException( "Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e, @@ -498,15 +499,16 @@ public class ODataJsonDeserializer implements ODataDeserializer { private Object readEnumValue(EdmProperty edmProperty, JsonNode jsonNode) throws DeserializerException { checkForValueNode(edmProperty, jsonNode); - if(isValidNull(edmProperty, jsonNode)) { + if (isValidNull(edmProperty, jsonNode)) { return null; } try { EdmEnumType edmEnumType = (EdmEnumType) edmProperty.getType(); checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmEnumType.getUnderlyingType().getName(), jsonNode); + Class javaClass = getJavaClassForPrimitiveType(edmProperty, edmEnumType.getUnderlyingType()); return edmEnumType .valueOfString(jsonNode.asText(), edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty - .getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), edmEnumType.getDefaultType()); + .getPrecision(), edmProperty.getScale(), edmProperty.isUnicode(), javaClass); } catch (EdmPrimitiveTypeException e) { throw new DeserializerException( "Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e, @@ -516,15 +518,16 @@ public class ODataJsonDeserializer implements ODataDeserializer { private Object readPrimitiveValue(EdmProperty edmProperty, JsonNode jsonNode) throws DeserializerException { checkForValueNode(edmProperty, jsonNode); - if(isValidNull(edmProperty, jsonNode)) { + if (isValidNull(edmProperty, jsonNode)) { return null; } try { EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmProperty.getType(); checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmPrimitiveType.getName(), jsonNode); + Class javaClass = getJavaClassForPrimitiveType(edmProperty, edmPrimitiveType); return edmPrimitiveType.valueOfString(jsonNode.asText(), edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(), - edmProperty.isUnicode(), edmPrimitiveType.getDefaultType()); + edmProperty.isUnicode(), javaClass); } catch (EdmPrimitiveTypeException e) { throw new DeserializerException( "Invalid value: " + jsonNode.asText() + " for property: " + edmProperty.getName(), e, @@ -532,6 +535,24 @@ public class ODataJsonDeserializer implements ODataDeserializer { } } + /** + * This method either returns the primitive types default class or the manually mapped class if present. + * @param edmProperty + * @param edmPrimitiveType + * @return the java class to be used during deserialization + */ + private 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; + } + /** * Check if JsonNode is a value node (jsonNode.isValueNode()) and if not throw * an DeserializerException. diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmMappingTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmMappingTest.java new file mode 100644 index 000000000..5f0ccfda8 --- /dev/null +++ b/lib/server-core/src/test/java/org/apache/olingo/server/core/edm/provider/EdmMappingTest.java @@ -0,0 +1,70 @@ +/* + * 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.edm.provider; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Date; + +import org.apache.olingo.commons.api.edm.EdmParameter; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.server.api.edm.provider.Mapping; +import org.apache.olingo.server.api.edm.provider.Parameter; +import org.apache.olingo.server.api.edm.provider.Property; +import org.junit.Test; + +public class EdmMappingTest { + + @Test + public void initialMappingMustBeNull() { + Property property = new Property().setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName()); + EdmProperty edmProperty = new EdmPropertyImpl(null, new FullQualifiedName("namespace.name"), property); + + assertNull(edmProperty.getMapping()); + + Parameter parameter = new Parameter().setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName()); + EdmParameter edmParameter = new EdmParameterImpl(null, parameter); + + assertNull(edmParameter.getMapping()); + } + + @Test + public void getDataClassForPrimTypeViaMapping() { + Mapping mapping = new Mapping().setMappedJavaClass(Date.class); + Property property = new Property() + .setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName()) + .setMapping(mapping); + EdmProperty edmProperty = new EdmPropertyImpl(null, new FullQualifiedName("namespace.name"), property); + + assertNotNull(edmProperty.getMapping()); + assertEquals(Date.class, edmProperty.getMapping().getMappedJavaClass()); + + Parameter parameter = new Parameter() + .setType(EdmPrimitiveTypeKind.DateTime.getFullQualifiedName()) + .setMapping(mapping); + EdmParameter edmParameter = new EdmParameterImpl(null, parameter); + + assertNotNull(edmParameter.getMapping()); + assertEquals(Date.class, edmParameter.getMapping().getMappedJavaClass()); + } +} diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java index 6c48d73ed..f80a4e468 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java @@ -24,10 +24,15 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; import java.util.List; import org.apache.olingo.commons.api.data.Entity; @@ -35,11 +40,19 @@ import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.domain.ODataLinkType; +import org.apache.olingo.commons.api.edm.Edm; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.format.ODataFormat; +import org.apache.olingo.commons.core.edm.primitivetype.EdmDate; +import org.apache.olingo.commons.core.edm.primitivetype.EdmDateTimeOffset; import org.apache.olingo.server.api.OData; import org.apache.olingo.server.api.deserializer.DeserializerException; import org.apache.olingo.server.api.deserializer.ODataDeserializer; +import org.apache.olingo.server.api.edm.provider.Mapping; +import org.apache.olingo.server.api.edmx.EdmxReference; +import org.apache.olingo.server.tecsvc.provider.EdmTechProvider; import org.junit.Test; public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTest { @@ -106,26 +119,26 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void simpleEntityETAllPrimWithDefaultNullValue() throws Exception { String entityString = - "{\"PropertyInt16\":32767," + - "\"PropertyString\":\"First Resource - positive values\"," + - "\"PropertyBoolean\":null," + - "\"PropertyByte\":255," + - "\"PropertySByte\":127," + - "\"PropertyInt32\":2147483647," + - "\"PropertyInt64\":9223372036854775807," + - "\"PropertySingle\":1.79E20," + - "\"PropertyDouble\":-1.79E19," + - "\"PropertyDecimal\":34," + - "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + - "\"PropertyDate\":null," + - "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + - "\"PropertyDuration\":\"PT6S\"," + - "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + - "\"PropertyTimeOfDay\":\"03:26:05\"}"; + "{\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":null," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":null," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = - deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))); + deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))); assertNotNull(entity); List properties = entity.getProperties(); assertNotNull(properties); @@ -155,26 +168,26 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void simpleEntityETNoneNullable() throws Exception { String entityString = - "{\"PropertyInt16\":32767," + - "\"PropertyString\":\"First Resource - positive values\"," + - "\"PropertyBoolean\":null," + - "\"PropertyByte\":255," + - "\"PropertySByte\":127," + - "\"PropertyInt32\":2147483647," + - "\"PropertyInt64\":9223372036854775807," + - "\"PropertySingle\":1.79E20," + - "\"PropertyDouble\":-1.79E19," + - "\"PropertyDecimal\":34," + - "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + - "\"PropertyDate\":null," + - "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + - "\"PropertyDuration\":\"PT6S\"," + - "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + - "\"PropertyTimeOfDay\":\"03:26:05\"}"; + "{\"PropertyInt16\":32767," + + "\"PropertyString\":\"First Resource - positive values\"," + + "\"PropertyBoolean\":null," + + "\"PropertyByte\":255," + + "\"PropertySByte\":127," + + "\"PropertyInt32\":2147483647," + + "\"PropertyInt64\":9223372036854775807," + + "\"PropertySingle\":1.79E20," + + "\"PropertyDouble\":-1.79E19," + + "\"PropertyDecimal\":34," + + "\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"PropertyDate\":null," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"," + + "\"PropertyDuration\":\"PT6S\"," + + "\"PropertyGuid\":\"01234567-89ab-cdef-0123-456789abcdef\"," + + "\"PropertyTimeOfDay\":\"03:26:05\"}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = - deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))); + deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"))); assertNotNull(entity); List properties = entity.getProperties(); assertNotNull(properties); @@ -489,7 +502,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = deserializer.entity(stream, edm - .getEntityType(new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); + .getEntityType(new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); assertEquals(6, entity.getProperties().size()); @@ -509,31 +522,31 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void eTCollAllPrimWithNullValue() throws Exception { final String entityString = "{" - + "\"PropertyInt16\":1," - + "\"CollPropertyString\":" - + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]," - + "\"CollPropertyBoolean\":[true,null,false]," - + "\"CollPropertyByte\":[50,200,249]," - + "\"CollPropertySByte\":[-120,120,126]," - + "\"CollPropertyInt16\":[1000,2000,30112]," - + "\"CollPropertyInt32\":[23232323,11223355,10000001]," - + "\"CollPropertyInt64\":[929292929292,333333333333,444444444444]," - + "\"CollPropertySingle\":[1790.0,26600.0,3210.0]," - + "\"CollPropertyDouble\":[-17900.0,-2.78E7,3210.0]," - + "\"CollPropertyDecimal\":[12,-2,1234]," - + "\"CollPropertyBinary\":[\"q83v\",\"ASNF\",\"VGeJ\"]," - + "\"CollPropertyDate\":[\"1958-12-03\",\"1999-08-05\",\"2013-06-25\"]," - + "\"CollPropertyDateTimeOffset\":[\"2015-08-12T03:08:34Z\",\"1970-03-28T12:11:10Z\"," - + "\"1948-02-17T09:09:09Z\"]," - + "\"CollPropertyDuration\":[\"PT13S\",\"PT5H28M0S\",\"PT1H0S\"]," - + "\"CollPropertyGuid\":[\"ffffff67-89ab-cdef-0123-456789aaaaaa\",\"eeeeee67-89ab-cdef-0123-456789bbbbbb\"," - + "\"cccccc67-89ab-cdef-0123-456789cccccc\"]," - + "\"CollPropertyTimeOfDay\":[\"04:14:13\",\"23:59:59\",\"01:12:33\"]" - + "}"; + + "\"PropertyInt16\":1," + + "\"CollPropertyString\":" + + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"]," + + "\"CollPropertyBoolean\":[true,null,false]," + + "\"CollPropertyByte\":[50,200,249]," + + "\"CollPropertySByte\":[-120,120,126]," + + "\"CollPropertyInt16\":[1000,2000,30112]," + + "\"CollPropertyInt32\":[23232323,11223355,10000001]," + + "\"CollPropertyInt64\":[929292929292,333333333333,444444444444]," + + "\"CollPropertySingle\":[1790.0,26600.0,3210.0]," + + "\"CollPropertyDouble\":[-17900.0,-2.78E7,3210.0]," + + "\"CollPropertyDecimal\":[12,-2,1234]," + + "\"CollPropertyBinary\":[\"q83v\",\"ASNF\",\"VGeJ\"]," + + "\"CollPropertyDate\":[\"1958-12-03\",\"1999-08-05\",\"2013-06-25\"]," + + "\"CollPropertyDateTimeOffset\":[\"2015-08-12T03:08:34Z\",\"1970-03-28T12:11:10Z\"," + + "\"1948-02-17T09:09:09Z\"]," + + "\"CollPropertyDuration\":[\"PT13S\",\"PT5H28M0S\",\"PT1H0S\"]," + + "\"CollPropertyGuid\":[\"ffffff67-89ab-cdef-0123-456789aaaaaa\",\"eeeeee67-89ab-cdef-0123-456789bbbbbb\"," + + "\"cccccc67-89ab-cdef-0123-456789cccccc\"]," + + "\"CollPropertyTimeOfDay\":[\"04:14:13\",\"23:59:59\",\"01:12:33\"]" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity e = deserializer.entity(stream, edm.getEntityType( - new FullQualifiedName("Namespace1_Alias", "ETCollAllPrim"))); + new FullQualifiedName("Namespace1_Alias", "ETCollAllPrim"))); assertTrue((Boolean) e.getProperty("CollPropertyBoolean").asCollection().get(0)); assertNull(e.getProperty("CollPropertyBoolean").asCollection().get(1)); @@ -543,27 +556,28 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void validJsonValueForComplexTypeNull() throws Exception { final String entityString = "{" - + "\"PropertyComp\":null" - + "}"; + + "\"PropertyComp\":null" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", - "ETMixPrimCollComp"))); + "ETMixPrimCollComp"))); assertNull(entity.getProperty("PropertyComp").getValue()); } + @SuppressWarnings("unchecked") @Test public void validJsonValueForComplexCollectionNullValue() throws Exception { final String entityString = "{" - + "\"CollPropertyComp\":[" - + "null," - + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}"; + + "\"CollPropertyComp\":[" + + "null," + + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = deserializer.entity(stream, edm.getEntityType( - new FullQualifiedName("Namespace1_Alias", "ETMixPrimCollComp"))); + new FullQualifiedName("Namespace1_Alias", "ETMixPrimCollComp"))); List collPropertyComp = entity.getProperty("CollPropertyComp").asCollection(); assertNull(collPropertyComp.get(0)); List complexPropertyProperties = (List) collPropertyComp.get(1); @@ -574,12 +588,12 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void validJsonValueForPrimPropertyInComplexTypeNull() throws Exception { final String entityString = "{" - + "\"PropertyComp\":{\"PropertyString\":\"TEST A\",\"PropertyInt16\":null}" - + "}"; + + "\"PropertyComp\":{\"PropertyString\":\"TEST A\",\"PropertyInt16\":null}" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity entity = deserializer.entity(stream, edm.getEntityType( - new FullQualifiedName("Namespace1_Alias", "ETCompAllPrim"))); + new FullQualifiedName("Namespace1_Alias", "ETCompAllPrim"))); assertEquals("TEST A", entity.getProperty("PropertyComp").asComplex().get(0).getValue()); assertNull(entity.getProperty("PropertyComp").asComplex().get(1).getValue()); @@ -588,21 +602,65 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test public void eTMixEnumDefCollCompNavValidComplexEnumValueNull() throws Exception { String entityString = "{" - + "\"PropertyEnumString\" : 2," - + "\"PropertyCompMixedEnumDef\" : {" - + "\"PropertyEnumString\" : null" - + "}}"; + + "\"PropertyEnumString\" : 2," + + "\"PropertyCompMixedEnumDef\" : {" + + "\"PropertyEnumString\" : null" + + "}}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity e = deserializer.entity(stream, edm.getEntityType( - new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); + new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); assertEquals(Short.valueOf("2"), e.getProperty("PropertyEnumString").getValue()); Property propertyCompMixedEnumDef = e.getProperty("PropertyCompMixedEnumDef"); assertNull(propertyCompMixedEnumDef.asComplex().get(0).getValue()); } + @SuppressWarnings("unused") + @Test + public void mappingTest() throws Exception { + Edm localEdm = + OData.newInstance().createServiceMetadata(new EdmTechProvider(), Collections. emptyList()) + .getEdm(); + + EdmEntityType entityType = mock(EdmEntityType.class); + when(entityType.getFullQualifiedName()).thenReturn(new FullQualifiedName("napespace", "name")); + List propertyNames = new ArrayList(); + propertyNames.add("PropertyDate"); + propertyNames.add("PropertyDateTimeOffset"); + when(entityType.getPropertyNames()).thenReturn(propertyNames); + Mapping mapping = new Mapping().setMappedJavaClass(Date.class); + + EdmProperty propertyDate = mock(EdmProperty.class); + when(propertyDate.getName()).thenReturn("PropertyDate"); + when(propertyDate.getMapping()).thenReturn(mapping); + when(propertyDate.getType()).thenReturn(new EdmDate()); + when(entityType.getProperty("PropertyDate")).thenReturn(propertyDate); + + EdmProperty propertyDateTimeOffset = mock(EdmProperty.class); + when(propertyDateTimeOffset.getName()).thenReturn("PropertyDateTimeOffset"); + when(propertyDateTimeOffset.getMapping()).thenReturn(mapping); + when(propertyDateTimeOffset.getType()).thenReturn(new EdmDateTimeOffset()); + when(entityType.getProperty("PropertyDateTimeOffset")).thenReturn(propertyDateTimeOffset); + + String entityString = + "{\"PropertyDate\":\"2012-12-03\"," + + "\"PropertyDateTimeOffset\":\"2012-12-03T07:16:23Z\"}"; + InputStream stream = new ByteArrayInputStream(entityString.getBytes()); + ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); + Entity entity = + deserializer.entity(stream, entityType); + assertNotNull(entity); + List properties = entity.getProperties(); + assertNotNull(properties); + assertEquals(2, properties.size()); + + assertNotNull(entity.getProperty("PropertyDate").getValue()); + assertEquals(Date.class, entity.getProperty("PropertyDate").getValue().getClass()); + assertNotNull(entity.getProperty("PropertyDateTimeOffset").getValue()); + assertEquals(Date.class, entity.getProperty("PropertyDateTimeOffset").getValue().getClass()); + } // ---------------------------------- Negative Tests ----------------------------------------------------------- @@ -1165,10 +1223,10 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test(expected = DeserializerException.class) public void invalidNullValueForPrimBeforeComplexTypeNullableFalse() throws Exception { final String entityString = "{" - + "\"PropertyInt16\": null, \"PropertyString\": \"321\", " - + "\"PropertyComp\":{\"PropertyInt16\": null, " - + "\"PropertyComp\": {\"PropertyString\":\"StringValue\"}}" - + "}"; + + "\"PropertyInt16\": null, \"PropertyString\": \"321\", " + + "\"PropertyComp\":{\"PropertyInt16\": null, " + + "\"PropertyComp\": {\"PropertyString\":\"StringValue\"}}" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); try { @@ -1182,9 +1240,9 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test(expected = DeserializerException.class) public void invalidNullValueForComplexTypePropertyNullableFalse() throws Exception { final String entityString = "{" - + "\"PropertyInt16\": 123, " - + "\"PropertyCompTwoPrim\":{\"PropertyInt16\": null, \"PropertyString\":\"StringValue\"}" - + "}"; + + "\"PropertyInt16\": 123, " + + "\"PropertyCompTwoPrim\":{\"PropertyInt16\": null, \"PropertyString\":\"StringValue\"}" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); try { @@ -1214,8 +1272,8 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe @Test(expected = DeserializerException.class) public void invalidNullValueForPrimIntCollectionNullableFalse() throws Exception { final String entityString = "{" - + "\"CollPropertyInt16\":[123,\"null\",4711]" - + "}"; + + "\"CollPropertyInt16\":[123,\"null\",4711]" + + "}"; InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); try { @@ -1252,7 +1310,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe InputStream stream = new ByteArrayInputStream(entityString.getBytes()); ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON); Entity e = deserializer.entity(stream, edm.getEntityType( - new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); + new FullQualifiedName("Namespace1_Alias", "ETMixEnumDefCollComp"))); assertNull(e.getProperty("PropertyEnumString").getValue()); Property propertyCompMixedEnumDef = e.getProperty("PropertyCompMixedEnumDef");