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/01/19 15:48:21 UTC

olingo-odata4 git commit: [OLINGO-530] Tests and JsonType Validation

Repository: olingo-odata4
Updated Branches:
  refs/heads/master af64cb1fa -> b6c1e347c


[OLINGO-530] Tests and JsonType Validation


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

Branch: refs/heads/master
Commit: b6c1e347c7b8b16d4184dd3d39b9ad0594d65e10
Parents: af64cb1
Author: Christian Amend <ch...@apache.org>
Authored: Mon Jan 19 15:47:19 2015 +0100
Committer: Christian Amend <ch...@apache.org>
Committed: Mon Jan 19 15:47:19 2015 +0100

----------------------------------------------------------------------
 .../api/deserializer/DeserializerException.java |   4 +-
 .../json/ODataJsonDeserializer.java             | 236 ++++++++-----------
 .../server-core-exceptions-i18n.properties      |  13 +
 .../json/ODataDeserializerDeepInsertTest.java   |  38 +++
 .../ODataDeserializerEntityCollectionTest.java  |  32 +++
 .../json/ODataJsonDeserializerEntityTest.java   | 218 ++++++++++++++++-
 .../ESAllPrimWithCustomAnnotations.json         |  57 +++++
 .../test/resources/ESAllPrimWithDoubleKey.json  |  57 +++++
 .../ESAllPrimWithODataAnnotations.json          |  59 +++++
 ...pertyETTwoPrimManyWithCustomAnnotations.json |  25 ++
 ...opertyETTwoPrimManyWithODataAnnotations.json |  27 +++
 ...opertyETTwoPrimOneWithCustomAnnotations.json |  24 ++
 ...ropertyETTwoPrimOneWithODataAnnotations.json |  26 ++
 13 files changed, 672 insertions(+), 144 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerException.java
----------------------------------------------------------------------
diff --git a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerException.java b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerException.java
index 6ecc2c8..5a9128f 100644
--- a/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerException.java
+++ b/lib/server-api/src/main/java/org/apache/olingo/server/api/deserializer/DeserializerException.java
@@ -40,7 +40,9 @@ public class DeserializerException extends ODataTranslatedException {
     VALUE_TAG_MUST_BE_AN_ARRAY, 
     INVALID_ENTITY, 
     /** parameter: navigationPropertyName */INVALID_VALUE_FOR_NAVIGATION_PROPERTY, 
-    DUPLICATE_PROPERTY;
+    DUPLICATE_PROPERTY, 
+    DUPLICATE_JSON_PROPERTY, 
+    /** parameters: primitiveTypeName, propertyName */ UNKNOWN_PRIMITIVE_TYPE;
 
     @Override
     public String getKey() {

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-core/src/main/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializer.java
----------------------------------------------------------------------
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 13c32ff..711b3db 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
@@ -20,14 +20,12 @@ package org.apache.olingo.server.core.deserializer.json;
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.apache.commons.lang3.StringUtils;
 import org.apache.olingo.commons.api.Constants;
 import org.apache.olingo.commons.api.data.Entity;
 import org.apache.olingo.commons.api.data.EntitySet;
@@ -40,13 +38,14 @@ import org.apache.olingo.commons.api.edm.EdmEnumType;
 import org.apache.olingo.commons.api.edm.EdmNavigationProperty;
 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.edm.EdmTypeDefinition;
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
 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.commons.core.data.PropertyImpl;
-import org.apache.olingo.commons.core.edm.EdmTypeInfo;
 import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.apache.olingo.server.api.deserializer.ODataDeserializer;
 
@@ -61,6 +60,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
 
 public class ODataJsonDeserializer implements ODataDeserializer {
 
+  private static final String ODATA_ANNOTATION_MARKER = "@";
+  private static final String ODATA_CONTROL_INFORMATION_PREFIX = "@odata.";
+
   @Override
   public EntitySet entityCollection(InputStream stream, EdmEntityType edmEntityType) throws DeserializerException {
     try {
@@ -74,8 +76,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       throw new DeserializerException("An JsonParseException occourred", e,
           DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
     } catch (JsonMappingException e) {
-      throw new DeserializerException("Duplicate property detected", e,
-          DeserializerException.MessageKeys.DUPLICATE_PROPERTY);
+      throw new DeserializerException("Duplicate json property detected", e,
+          DeserializerException.MessageKeys.DUPLICATE_JSON_PROPERTY);
     } catch (IOException e) {
       throw new DeserializerException("An IOException occourred", e, DeserializerException.MessageKeys.IO_EXCEPTION);
     }
@@ -84,8 +86,6 @@ public class ODataJsonDeserializer implements ODataDeserializer {
   private EntitySet consumeEntitySetNode(EdmEntityType edmEntityType, final ObjectNode tree)
       throws DeserializerException {
     EntitySetImpl entitySet = new EntitySetImpl();
-    // Consume entitySet annotations
-    consumeODataEntitySetAnnotations(tree, entitySet);
 
     // Consume entities
     JsonNode jsonNode = tree.get(Constants.VALUE);
@@ -102,6 +102,22 @@ public class ODataJsonDeserializer implements ODataDeserializer {
           DeserializerException.MessageKeys.VALUE_ARRAY_NOT_PRESENT);
     }
 
+    final List<String> toRemove = new ArrayList<String>();
+    Iterator<Entry<String, JsonNode>> fieldsIterator = tree.fields();
+    while (fieldsIterator.hasNext()) {
+      Map.Entry<String, JsonNode> field = fieldsIterator.next();
+
+      if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
+        // Control Information is ignored for requests as per specification chapter "4.5 Control Information"
+        toRemove.add(field.getKey());
+      } else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
+        throw new DeserializerException("Custom annotation with field name: " + field.getKey() + " not supported",
+            DeserializerException.MessageKeys.NOT_IMPLEMENTED);
+      }
+    }
+    // remove here to avoid iterator issues.
+    tree.remove(toRemove);
+
     if (tree.size() != 0) {
       throw new DeserializerException("Tree should be empty but still has content left.",
           DeserializerException.MessageKeys.UNKOWN_CONTENT);
@@ -123,35 +139,6 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
   }
 
-  private void consumeODataEntitySetAnnotations(final ObjectNode tree, EntitySetImpl entitySet) {
-    URI contextURL;
-    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
-      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
-      tree.remove(Constants.JSON_CONTEXT);
-    } else if (tree.hasNonNull(Constants.JSON_METADATA)) {
-      contextURL = URI.create(tree.get(Constants.JSON_METADATA).textValue());
-      tree.remove(Constants.JSON_METADATA);
-    } else {
-      contextURL = null;
-    }
-    if (contextURL != null) {
-      entitySet.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
-    }
-
-    if (tree.hasNonNull(Constants.JSON_COUNT)) {
-      entitySet.setCount(tree.get(Constants.JSON_COUNT).asInt());
-      tree.remove(Constants.JSON_COUNT);
-    }
-    if (tree.hasNonNull(Constants.JSON_NEXT_LINK)) {
-      entitySet.setNext(URI.create(tree.get(Constants.JSON_NEXT_LINK).textValue()));
-      tree.remove(Constants.JSON_NEXT_LINK);
-    }
-    if (tree.hasNonNull(Constants.JSON_DELTA_LINK)) {
-      entitySet.setDeltaLink(URI.create(tree.get(Constants.JSON_DELTA_LINK).textValue()));
-      tree.remove(Constants.JSON_DELTA_LINK);
-    }
-  }
-
   @Override
   public Entity entity(InputStream stream, EdmEntityType edmEntityType) throws DeserializerException {
     try {
@@ -231,19 +218,17 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       }
     }
 
-    // Check and consume all Annotations
-    consumeODataEntityAnnotations(tree, entity, edmEntityType);
-
     final List<String> toRemove = new ArrayList<String>();
     Iterator<Entry<String, JsonNode>> fieldsIterator = tree.fields();
-    // TODO: Add custom annotation support
     while (fieldsIterator.hasNext()) {
-      Map.Entry<String, JsonNode> field = (Map.Entry<String, JsonNode>) fieldsIterator.next();
+      Map.Entry<String, JsonNode> field = fieldsIterator.next();
 
-      if (field.getKey().endsWith(Constants.JSON_NAVIGATION_LINK)
-          || field.getKey().endsWith(Constants.JSON_ASSOCIATION_LINK) || field.getKey().endsWith(Constants.JSON_TYPE)) {
-        // navigation links, association links and type information have to be ignored in requests.
+      if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
+        // Control Information is ignored for requests as per specification chapter "4.5 Control Information"
         toRemove.add(field.getKey());
+      } else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
+        throw new DeserializerException("Custom annotation with field name: " + field.getKey() + " not supported",
+            DeserializerException.MessageKeys.NOT_IMPLEMENTED);
       }
     }
 
@@ -259,75 +244,6 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     return entity;
   }
 
-  private void consumeODataEntityAnnotations(ObjectNode tree, EntityImpl entity, EdmEntityType edmEntityType) {
-    final URI contextURL;
-    if (tree.hasNonNull(Constants.JSON_CONTEXT)) {
-      contextURL = URI.create(tree.get(Constants.JSON_CONTEXT).textValue());
-      tree.remove(Constants.JSON_CONTEXT);
-    } else if (tree.hasNonNull(Constants.JSON_METADATA)) {
-      contextURL = URI.create(tree.get(Constants.JSON_METADATA).textValue());
-      tree.remove(Constants.JSON_METADATA);
-    } else {
-      contextURL = null;
-    }
-    if (contextURL != null) {
-      entity.setBaseURI(StringUtils.substringBefore(contextURL.toASCIIString(), Constants.METADATA));
-    }
-
-    if (tree.hasNonNull(Constants.JSON_ETAG)) {
-      entity.setETag(tree.get(Constants.JSON_ETAG).textValue());
-      tree.remove(Constants.JSON_ETAG);
-    }
-
-    if (tree.hasNonNull(Constants.JSON_TYPE)) {
-      entity.setType(new EdmTypeInfo.Builder().setTypeExpression(tree.get(Constants.JSON_TYPE).textValue()).build()
-          .internal());
-      tree.remove(Constants.JSON_TYPE);
-    }
-
-    if (tree.hasNonNull(Constants.JSON_ID)) {
-      entity.setId(URI.create(tree.get(Constants.JSON_ID).textValue()));
-      tree.remove(Constants.JSON_ID);
-    }
-
-    if (tree.hasNonNull(Constants.JSON_READ_LINK)) {
-      final LinkImpl link = new LinkImpl();
-      link.setRel(Constants.SELF_LINK_REL);
-      link.setHref(tree.get(Constants.JSON_READ_LINK).textValue());
-      entity.setSelfLink(link);
-
-      tree.remove(Constants.JSON_READ_LINK);
-    }
-
-    if (tree.hasNonNull(Constants.JSON_EDIT_LINK)) {
-      final LinkImpl link = new LinkImpl();
-      link.setRel(Constants.EDIT_LINK_REL);
-      link.setHref(tree.get(Constants.JSON_EDIT_LINK).textValue());
-      entity.setEditLink(link);
-
-      tree.remove(Constants.JSON_EDIT_LINK);
-    }
-
-    // TODO: Should we check if this is a media resource?
-    if (tree.hasNonNull(Constants.JSON_MEDIA_READ_LINK)) {
-      entity.setMediaContentSource(URI.create(tree.get(Constants.JSON_MEDIA_READ_LINK).textValue()));
-      tree.remove(Constants.JSON_MEDIA_READ_LINK);
-    }
-    if (tree.hasNonNull(Constants.JSON_MEDIA_EDIT_LINK)) {
-      entity.setMediaContentSource(URI.create(tree.get(Constants.JSON_MEDIA_EDIT_LINK).textValue()));
-      tree.remove(Constants.JSON_MEDIA_EDIT_LINK);
-    }
-    if (tree.hasNonNull(Constants.JSON_MEDIA_CONTENT_TYPE)) {
-      entity.setMediaContentType(tree.get(Constants.JSON_MEDIA_CONTENT_TYPE).textValue());
-      tree.remove(Constants.JSON_MEDIA_CONTENT_TYPE);
-    }
-    if (tree.hasNonNull(Constants.JSON_MEDIA_ETAG)) {
-      entity.setMediaETag(tree.get(Constants.JSON_MEDIA_ETAG).textValue());
-      tree.remove(Constants.JSON_MEDIA_ETAG);
-    }
-
-  }
-
   private Property consumePropertyNode(EdmProperty edmProperty, JsonNode jsonNode) throws DeserializerException {
     Property property = new PropertyImpl();
     property.setName(edmProperty.getName());
@@ -356,6 +272,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
           valueArray.add(value);
         }
         property.setValue(ValueType.COLLECTION_PRIMITIVE, valueArray);
+        break;
       case ENUM:
         while (iterator.hasNext()) {
           JsonNode arrayElement = iterator.next();
@@ -370,19 +287,19 @@ public class ODataJsonDeserializer implements ODataDeserializer {
           // read and add all complex properties
           Object value = readComplexValue(edmProperty, arrayElement);
           valueArray.add(value);
-          // If navigationProperties are present we have to consume them and create a LinkedComplexValue Object
-          // TODO: Complex Type Navigation Deserialization
+
           final List<String> toRemove = new ArrayList<String>();
           Iterator<Entry<String, JsonNode>> fieldsIterator = arrayElement.fields();
-          // TODO: Add custom annotation support
           while (fieldsIterator.hasNext()) {
-            Map.Entry<String, JsonNode> field = (Map.Entry<String, JsonNode>) fieldsIterator.next();
+            Map.Entry<String, JsonNode> field = fieldsIterator.next();
 
-            if (field.getKey().endsWith(Constants.JSON_NAVIGATION_LINK)
-                || field.getKey().endsWith(Constants.JSON_ASSOCIATION_LINK)
-                || field.getKey().endsWith(Constants.JSON_TYPE)) {
-              // navigation links, association links and type information have to be ignored in requests.
+            if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
+              // Control Information is ignored for requests as per specification chapter "4.5 Control Information"
               toRemove.add(field.getKey());
+            } else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
+              throw new DeserializerException(
+                  "Custom annotation with field name: " + field.getKey() + " not supported",
+                  DeserializerException.MessageKeys.NOT_IMPLEMENTED);
             }
           }
           // remove here to avoid iterator issues.
@@ -410,6 +327,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
       case DEFINITION:
         value = readTypeDefinitionValue(edmProperty, jsonNode);
         property.setValue(ValueType.PRIMITIVE, value);
+        break;
       case ENUM:
         value = readEnumValue(edmProperty, jsonNode);
         property.setValue(ValueType.PRIMITIVE, value);
@@ -419,19 +337,17 @@ public class ODataJsonDeserializer implements ODataDeserializer {
         value = readComplexValue(edmProperty, jsonNode);
         property.setValue(ValueType.COMPLEX, value);
 
-        // read and add all navigation properties
-        // TODO: Complex Type Navigation Deserialization
         final List<String> toRemove = new ArrayList<String>();
         Iterator<Entry<String, JsonNode>> fieldsIterator = jsonNode.fields();
-        // TODO: Add custom annotation support
         while (fieldsIterator.hasNext()) {
-          Map.Entry<String, JsonNode> field = (Map.Entry<String, JsonNode>) fieldsIterator.next();
+          Map.Entry<String, JsonNode> field = fieldsIterator.next();
 
-          if (field.getKey().endsWith(Constants.JSON_NAVIGATION_LINK)
-              || field.getKey().endsWith(Constants.JSON_ASSOCIATION_LINK)
-              || field.getKey().endsWith(Constants.JSON_TYPE)) {
-            // navigation links, association links and type information have to be ignored in requests.
+          if (field.getKey().contains(ODATA_CONTROL_INFORMATION_PREFIX)) {
+            // Control Information is ignored for requests as per specification chapter "4.5 Control Information"
             toRemove.add(field.getKey());
+          } else if (field.getKey().contains(ODATA_ANNOTATION_MARKER)) {
+            throw new DeserializerException("Custom annotation with field name: " + field.getKey() + " not supported",
+                DeserializerException.MessageKeys.NOT_IMPLEMENTED);
           }
         }
         // remove here to avoid iterator issues.
@@ -485,6 +401,8 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
     try {
       EdmTypeDefinition edmTypeDefinition = (EdmTypeDefinition) edmProperty.getType();
+      checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmTypeDefinition.getUnderlyingType().getName(),
+          jsonNode);
       Object value =
           edmTypeDefinition.valueOfString(jsonNode.asText(), edmProperty.isNullable(),
               edmTypeDefinition.getMaxLength(),
@@ -506,6 +424,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
     try {
       EdmEnumType edmEnumType = (EdmEnumType) edmProperty.getType();
+      checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmEnumType.getUnderlyingType().getName(), jsonNode);
       Object value =
           edmEnumType
               .valueOfString(jsonNode.asText(), edmProperty.isNullable(), edmProperty.getMaxLength(), edmProperty
@@ -526,6 +445,7 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
     try {
       EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmProperty.getType();
+      checkJsonTypeBasedOnPrimitiveType(edmProperty.getName(), edmPrimitiveType.getName(), jsonNode);
       Object value =
           edmPrimitiveType.valueOfString(jsonNode.asText(), edmProperty.isNullable(),
               edmProperty.getMaxLength(), edmProperty.getPrecision(), edmProperty.getScale(),
@@ -538,13 +458,53 @@ public class ODataJsonDeserializer implements ODataDeserializer {
     }
   }
 
-//  @Override
-//  public Entity entity(InputStream stream, EdmEntityType edmEntityType)
-//      throws DeserializerException {
-//    try {
-//      return new JsonDeserializer(ODataServiceVersion.V40, true).toEntity(stream).getPayload();
-//    } catch (Exception e) {
-//      throw new DeserializerException("", e, DeserializerException.MessageKeys.JSON_SYNTAX_EXCEPTION);
-//    }
-//  }
+  private void checkJsonTypeBasedOnPrimitiveType(String propertyName, String edmPrimitiveTypeName, JsonNode jsonNode)
+      throws DeserializerException {
+    EdmPrimitiveTypeKind primKind = null;
+    try {
+      primKind = EdmPrimitiveTypeKind.valueOf(ODataServiceVersion.V40, edmPrimitiveTypeName);
+    } catch (IllegalArgumentException e) {
+      throw new DeserializerException("Unkown Primitive Type: " + edmPrimitiveTypeName, e,
+          DeserializerException.MessageKeys.UNKNOWN_PRIMITIVE_TYPE, edmPrimitiveTypeName, propertyName);
+    }
+    switch (primKind) {
+    // Booleans
+    case Boolean:
+      if (!jsonNode.isBoolean()) {
+        throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
+            + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+      }
+      break;
+    // Numbers
+    case Int16:
+    case Int32:
+    case Int64:
+    case Byte:
+    case SByte:
+    case Single:
+    case Double:
+    case Decimal:
+      if (!jsonNode.isNumber()) {
+        throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
+            + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+      }
+      break;
+//Strings
+    case String:
+    case Binary:
+    case Date:
+    case DateTimeOffset:
+    case Duration:
+    case Guid:
+    case TimeOfDay:
+      if (!jsonNode.isTextual()) {
+        throw new DeserializerException("Invalid json type: " + jsonNode.getNodeType() + " for edm " + primKind
+            + " property: " + propertyName, DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, propertyName);
+      }
+      break;
+    default:
+      throw new DeserializerException("Unsupported Edm Primitive Type: " + primKind,
+          DeserializerException.MessageKeys.NOT_IMPLEMENTED);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
index 034a6bd..eb31dd1 100644
--- a/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
+++ b/lib/server-core/src/main/resources/server-core-exceptions-i18n.properties
@@ -99,6 +99,19 @@ SerializerException.WRONG_PRIMITIVE_VALUE=The value '%2$s' is not valid for the
 
 DeserializerException.NOT_IMPLEMENTED=The requested deserialization method has not been implemented yet.
 DeserializerException.IO_EXCEPTION=An I/O exception occurred.
+DeserializerException.UNSUPPORTED_FORMAT=The format '%1$s' is not supported.
+DeserializerException.JSON_SYNTAX_EXCEPTION=The syntax of the JSON document is not valid.
+DeserializerException.INVALID_NULL_PROPERTY=The property '%1$s' must not be null.
+DeserializerException.UNKOWN_CONTENT='%1$s' can not be mapped as a property or an annotation.
+DeserializerException.INVALID_VALUE_FOR_PROPERTY=Invalid value for property '%1$s'.
+DeserializerException.INVALID_TYPE_FOR_PROPERTY=Invalid JSON type for property '%1$s'.
+DeserializerException.VALUE_ARRAY_NOT_PRESENT=Cannot find the value array. A collection needs at least an empty array. 
+DeserializerException.VALUE_TAG_MUST_BE_AN_ARRAY=Invalid JSON type for the value tag. Must be an Array. 
+DeserializerException.INVALID_ENTITY=Invalid JSON type for an entity. Must be a JSON object.
+DeserializerException.INVALID_VALUE_FOR_NAVIGATION_PROPERTY=Invalid value for navigation property '%1$s'. Must be an array for collections or for an entity either null or an object.
+DeserializerException.DUPLICATE_PROPERTY="Edm Properties must not appear twice within the same object."
+DeserializerException.DUPLICATE_JSON_PROPERTY="JSON properties must not appear twice within the same object."
+DeserializerException.UNKNOWN_PRIMITIVE_TYPE=Unknown primitive type '%1$s' for property '%2$s';
 
 BatchDeserializerException.INVALID_BOUNDARY=Invalid boundary at line '%1$s'.
 BatchDeserializerException.INVALID_CHANGESET_METHOD=Invalid method: a ChangeSet cannot contain retrieve requests at line '%1$s'.

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
index 3b90277..a2f61a9 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerDeepInsertTest.java
@@ -31,6 +31,7 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.junit.Test;
 
 public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTest {
@@ -51,6 +52,13 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
   }
 
   @Test
+  public void esAllPrimExpandedToOneWithODataAnnotations() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json");
+    OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
+  }
+
+  @Test
   public void esAllPrimExpandedToMany() throws Exception {
     EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
     InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimMany.json");
@@ -66,4 +74,34 @@ public class ODataDeserializerDeepInsertTest extends AbstractODataDeserializerTe
     assertEquals(1, navigationLink.getInlineEntitySet().getEntities().size());
   }
 
+  @Test
+  public void esAllPrimExpandedToManyWithODataAnnotations() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json");
+    OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void esAllPrimExpandedToOneWithCustomAnnotations() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json");
+    try {
+      OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
+      throw e;
+    }
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void esAllPrimExpandedToManyWithCustomAnnotations() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json");
+    try {
+      OData.newInstance().createDeserializer(ODataFormat.JSON).entity(stream, edmEntityType);
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
+      throw e;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
index 888722e..e9ebbde 100644
--- a/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataDeserializerEntityCollectionTest.java
@@ -32,6 +32,7 @@ import org.apache.olingo.commons.api.edm.EdmEntityType;
 import org.apache.olingo.commons.api.edm.FullQualifiedName;
 import org.apache.olingo.commons.api.format.ODataFormat;
 import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.deserializer.DeserializerException;
 import org.junit.Test;
 
 public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserializerTest {
@@ -82,4 +83,35 @@ public class ODataDeserializerEntityCollectionTest extends AbstractODataDeserial
 
     // Since entity deserialization is called we do not check all entities here excplicitly
   }
+
+  @Test
+  public void esAllPrimODataAnnotationsAreIgnored() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("ESAllPrimWithODataAnnotations.json");
+    OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void esAllPrimCustomAnnotationsLeadToNotImplemented() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("ESAllPrimWithCustomAnnotations.json");
+    try {
+      OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
+      throw e;
+    }
+  }
+  
+  @Test(expected = DeserializerException.class)
+  public void esAllPrimDoubleKeysLeadToException() throws Exception {
+    EdmEntityType edmEntityType = edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim"));
+    InputStream stream = getFileAsStream("ESAllPrimWithDoubleKey.json");
+    try {
+      OData.newInstance().createDeserializer(ODataFormat.JSON).entityCollection(stream, edmEntityType);
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.DUPLICATE_JSON_PROPERTY, e.getMessageKey());
+      throw e;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/java/org/apache/olingo/server/core/deserializer/json/ODataJsonDeserializerEntityTest.java
----------------------------------------------------------------------
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 a446825..dce010c 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
@@ -21,6 +21,7 @@ package org.apache.olingo.server.core.deserializer.json;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
@@ -35,7 +36,6 @@ import org.apache.olingo.commons.api.format.ODataFormat;
 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.junit.Ignore;
 import org.junit.Test;
 
 public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTest {
@@ -265,7 +265,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
   }
 
   @Test
-  public void ingoreSomeAnnotationsInEntityTypes() throws Exception {
+  public void ignoreSomeAnnotationsInEntityTypes() throws Exception {
     // We have to ignore @odata.navigation, @odata.association and @odata.type annotations on server side
     String entityString =
         "{\"PropertyInt16\":32767,"
@@ -280,7 +280,7 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
   }
 
   @Test
-  public void ingoreSomeAnnotationsInComplexTypes() throws Exception {
+  public void ignoreSomeAnnotationsInComplexTypes() throws Exception {
     final String entityString = "{"
         + "\"PropertyInt16\":32767,"
         + "\"CollPropertyString\":"
@@ -298,6 +298,32 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
     deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETMixPrimCollComp")));
   }
 
+  @Test
+  public void odataControlInformationIsIgnoredForRequests() throws Exception {
+    String entityString =
+        "{"
+            + "\"@odata.context\":\"http://localhost:8080\","
+            + "\"@odata.metadataEtag\":\"metadataEtag\","
+            + "\"@odata.id\":\"value\","
+            + "\"@odata.editLink\":\"value\","
+            + "\"@odata.readLink\":\"value\","
+            + "\"@odata.etag\":\"value\","
+            + "\"@odata.mediaEtag\":\"value\","
+            + "\"@odata.mediaReadLink\":\"value\","
+            + "\"@odata.mediaEditLink\":\"value\","
+            + "\"PropertyInt16\":32767,"
+            + "\"PropertyString\":\"First Resource - positive values\""
+            + "}";
+    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")));
+    assertNotNull(entity);
+    List<Property> properties = entity.getProperties();
+    assertNotNull(properties);
+    assertEquals(2, properties.size());
+  }
+
 //  ---------------------------------- Negative Tests -----------------------------------------------------------
 
   @Test(expected = DeserializerException.class)
@@ -452,9 +478,8 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
     }
   }
 
-  @Ignore
   @Test(expected = DeserializerException.class)
-  public void customAnnotationsLeadToNotImplemented() throws Exception {
+  public void customAnnotationInEntityLeadToNotImplemented() throws Exception {
     final String entityString = "{"
         + "\"PropertyInt16\":32767,"
         + "\"CollPropertyString@custom.annotation\": 12,"
@@ -477,6 +502,51 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
   }
 
   @Test(expected = DeserializerException.class)
+  public void customAnnotationInComplexValueLeadToNotImplemented() throws Exception {
+    final String entityString = "{"
+        + "\"PropertyInt16\":32767,"
+        + "\"CollPropertyString\":"
+        + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"],"
+        + "\"PropertyComp\":{\"PropertyInt16\":111," +
+        "\"CollPropertyString@custom.annotation\": 12,\"PropertyString\":\"TEST A\"},"
+        + "\"CollPropertyComp\":["
+        + "{\"PropertyInt16\":123,\"PropertyString\":\"TEST 1\"},"
+        + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"},"
+        + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}";
+
+    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
+    try {
+      ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
+      deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETMixPrimCollComp")));
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
+      throw e;
+    }
+  }
+
+  @Test(expected = DeserializerException.class)
+  public void customAnnotationInComplexCollectionValueLeadToNotImplemented() throws Exception {
+    final String entityString = "{"
+        + "\"PropertyInt16\":32767,"
+        + "\"CollPropertyString\":"
+        + "[\"Employee1@company.example\",\"Employee2@company.example\",\"Employee3@company.example\"],"
+        + "\"PropertyComp\":{\"PropertyInt16\":111,\"PropertyString\":\"TEST A\"},"
+        + "\"CollPropertyComp\":["
+        + "{\"PropertyInt16\":123,\"CollPropertyString@custom.annotation\": 12,\"PropertyString\":\"TEST 1\"},"
+        + "{\"PropertyInt16\":456,\"PropertyString\":\"TEST 2\"},"
+        + "{\"PropertyInt16\":789,\"PropertyString\":\"TEST 3\"}]}";
+
+    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
+    try {
+      ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
+      deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETMixPrimCollComp")));
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.NOT_IMPLEMENTED, e.getMessageKey());
+      throw e;
+    }
+  }
+
+  @Test(expected = DeserializerException.class)
   public void unkownContentInEntity() throws Exception {
     final String entityString = "{"
         + "\"PropertyInt16\":32767,"
@@ -543,4 +613,142 @@ public class ODataJsonDeserializerEntityTest extends AbstractODataDeserializerTe
     }
   }
 
+  @Test
+  public void propertyInt16JsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyInt16\":\"32767\"}");
+    checkPropertyJsonType("{\"PropertyInt16\":true}");
+    checkPropertyJsonType("{\"PropertyInt16\":[]}");
+    checkPropertyJsonType("{\"PropertyInt16\":{}}");
+  }
+
+  @Test
+  public void propertyInt32JsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyInt32\":\"2147483647\"}");
+    checkPropertyJsonType("{\"PropertyInt32\":true}");
+    checkPropertyJsonType("{\"PropertyInt32\":[]}");
+    checkPropertyJsonType("{\"PropertyInt32\":{}}");
+  }
+
+  @Test
+  public void propertyInt64JsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyInt64\":\"9223372036854775807\"}");
+    checkPropertyJsonType("{\"PropertyInt64\":true}");
+    checkPropertyJsonType("{\"PropertyInt64\":[]}");
+    checkPropertyJsonType("{\"PropertyInt64\":{}}");
+  }
+
+  @Test
+  public void propertyStringJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyString\":32767}");
+    checkPropertyJsonType("{\"PropertyString\":true}");
+    checkPropertyJsonType("{\"PropertyString\":[]}");
+    checkPropertyJsonType("{\"PropertyString\":{}}");
+  }
+
+  @Test
+  public void propertyBooleanJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyBoolean\":\"true\"}");
+    checkPropertyJsonType("{\"PropertyBoolean\":123}");
+    checkPropertyJsonType("{\"PropertyBoolean\":[]}");
+    checkPropertyJsonType("{\"PropertyBoolean\":{}}");
+  }
+
+  @Test
+  public void propertyByteJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyByte\":\"255\"}");
+    checkPropertyJsonType("{\"PropertyByte\":true}");
+    checkPropertyJsonType("{\"PropertyByte\":[]}");
+    checkPropertyJsonType("{\"PropertyByte\":{}}");
+  }
+
+  @Test
+  public void propertySByteJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertySByte\":\"127\"}");
+    checkPropertyJsonType("{\"PropertySByte\":true}");
+    checkPropertyJsonType("{\"PropertySByte\":[]}");
+    checkPropertyJsonType("{\"PropertySByte\":{}}");
+  }
+
+  @Test
+  public void propertySingleJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertySingle\":\"1.79E20\"}");
+    checkPropertyJsonType("{\"PropertySingle\":true}");
+    checkPropertyJsonType("{\"PropertySingle\":[]}");
+    checkPropertyJsonType("{\"PropertySingle\":{}}");
+  }
+
+  @Test
+  public void propertyDoubleJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyDouble\":\"-1.79E19\"}");
+    checkPropertyJsonType("{\"PropertyDouble\":true}");
+    checkPropertyJsonType("{\"PropertyDouble\":[]}");
+    checkPropertyJsonType("{\"PropertyDouble\":{}}");
+  }
+
+  @Test
+  public void propertyDecimalJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyDecimal\":\"34\"}");
+    checkPropertyJsonType("{\"PropertyDecimal\":true}");
+    checkPropertyJsonType("{\"PropertyDecimal\":[]}");
+    checkPropertyJsonType("{\"PropertyDecimal\":{}}");
+  }
+
+  @Test
+  public void propertyBinaryJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyBinary\":32767}");
+    checkPropertyJsonType("{\"PropertyBinary\":true}");
+    checkPropertyJsonType("{\"PropertyBinary\":[]}");
+    checkPropertyJsonType("{\"PropertyBinary\":{}}");
+  }
+
+  @Test
+  public void propertyDateJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyDate\":32767}");
+    checkPropertyJsonType("{\"PropertyDate\":true}");
+    checkPropertyJsonType("{\"PropertyDate\":[]}");
+    checkPropertyJsonType("{\"PropertyDate\":{}}");
+  }
+
+  @Test
+  public void propertyDateTimeOffsetJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyDateTimeOffset\":32767}");
+    checkPropertyJsonType("{\"PropertyDateTimeOffset\":true}");
+    checkPropertyJsonType("{\"PropertyDateTimeOffset\":[]}");
+    checkPropertyJsonType("{\"PropertyDateTimeOffset\":{}}");
+  }
+
+  @Test
+  public void propertyDurationJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyDuration\":32767}");
+    checkPropertyJsonType("{\"PropertyDuration\":true}");
+    checkPropertyJsonType("{\"PropertyDuration\":[]}");
+    checkPropertyJsonType("{\"PropertyDuration\":{}}");
+  }
+
+  @Test
+  public void propertyGuidTimeOffsetJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyGuid\":32767}");
+    checkPropertyJsonType("{\"PropertyGuid\":true}");
+    checkPropertyJsonType("{\"PropertyGuid\":[]}");
+    checkPropertyJsonType("{\"PropertyGuid\":{}}");
+  }
+
+  @Test
+  public void propertyTimeOfDayJsonTypesNegativeCheck() throws Exception {
+    checkPropertyJsonType("{\"PropertyTimeOfDay\":32767}");
+    checkPropertyJsonType("{\"PropertyTimeOfDay\":true}");
+    checkPropertyJsonType("{\"PropertyTimeOfDay\":[]}");
+    checkPropertyJsonType("{\"PropertyTimeOfDay\":{}}");
+  }
+
+  private void checkPropertyJsonType(String entityString) throws DeserializerException {
+    InputStream stream = new ByteArrayInputStream(entityString.getBytes());
+    ODataDeserializer deserializer = OData.newInstance().createDeserializer(ODataFormat.JSON);
+    try {
+      deserializer.entity(stream, edm.getEntityType(new FullQualifiedName("Namespace1_Alias", "ETAllPrim")));
+      fail("Expected an exception but was not thrown: " + this.getClass().getName());
+    } catch (DeserializerException e) {
+      assertEquals(DeserializerException.MessageKeys.INVALID_VALUE_FOR_PROPERTY, e.getMessageKey());
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/ESAllPrimWithCustomAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/ESAllPrimWithCustomAnnotations.json b/lib/server-test/src/test/resources/ESAllPrimWithCustomAnnotations.json
new file mode 100644
index 0000000..915a3f0
--- /dev/null
+++ b/lib/server-test/src/test/resources/ESAllPrimWithCustomAnnotations.json
@@ -0,0 +1,57 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim",
+	"@custom.annotation" : "customValue",
+	"value" : [{
+			"PropertyInt16" : 32767,
+			"PropertyString" : "First Resource - positive values",
+			"PropertyBoolean" : true,
+			"PropertyByte" : 255,
+			"PropertySByte" : 127,
+			"PropertyInt32" : 2147483647,
+			"PropertyInt64" : 9223372036854775807,
+			"PropertySingle" : 1.79000000E+20,
+			"PropertyDouble" : -1.7900000000000000E+19,
+			"PropertyDecimal" : 34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2012-12-03",
+			"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+			"PropertyDuration" : "P0DT0H0M6S",
+			"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+			"PropertyTimeOfDay" : "03:26:05"
+		}, {
+			"PropertyInt16" : -32768,
+			"PropertyString" : "Second Resource - negative values",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : -128,
+			"PropertyInt32" : -2147483648,
+			"PropertyInt64" : -9223372036854775808,
+			"PropertySingle" : -1.79000000E+08,
+			"PropertyDouble" : -1.7900000000000000E+05,
+			"PropertyDecimal" : -34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2015-11-05",
+			"PropertyDateTimeOffset" : "2005-12-03T07:17:08Z",
+			"PropertyDuration" : "P0DT0H0M9S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789dddfff",
+			"PropertyTimeOfDay" : "23:49:14"
+		}, {
+			"PropertyInt16" : 0,
+			"PropertyString" : "",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : 0,
+			"PropertyInt32" : 0,
+			"PropertyInt64" : 0,
+			"PropertySingle" : 0.00000000E+00,
+			"PropertyDouble" : 0.0000000000000000E+00,
+			"PropertyDecimal" : 0,
+			"PropertyBinary" : "",
+			"PropertyDate" : "1970-01-01",
+			"PropertyDateTimeOffset" : "2005-12-03T00:00:00Z",
+			"PropertyDuration" : "P0DT0H0M0S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789cccddd",
+			"PropertyTimeOfDay" : "00:01:01"
+		}
+	]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/ESAllPrimWithDoubleKey.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/ESAllPrimWithDoubleKey.json b/lib/server-test/src/test/resources/ESAllPrimWithDoubleKey.json
new file mode 100644
index 0000000..6c12ca1
--- /dev/null
+++ b/lib/server-test/src/test/resources/ESAllPrimWithDoubleKey.json
@@ -0,0 +1,57 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim",
+	"value" : [],
+	"value" : [{
+			"PropertyInt16" : 32767,
+			"PropertyString" : "First Resource - positive values",
+			"PropertyBoolean" : true,
+			"PropertyByte" : 255,
+			"PropertySByte" : 127,
+			"PropertyInt32" : 2147483647,
+			"PropertyInt64" : 9223372036854775807,
+			"PropertySingle" : 1.79000000E+20,
+			"PropertyDouble" : -1.7900000000000000E+19,
+			"PropertyDecimal" : 34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2012-12-03",
+			"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+			"PropertyDuration" : "P0DT0H0M6S",
+			"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+			"PropertyTimeOfDay" : "03:26:05"
+		}, {
+			"PropertyInt16" : -32768,
+			"PropertyString" : "Second Resource - negative values",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : -128,
+			"PropertyInt32" : -2147483648,
+			"PropertyInt64" : -9223372036854775808,
+			"PropertySingle" : -1.79000000E+08,
+			"PropertyDouble" : -1.7900000000000000E+05,
+			"PropertyDecimal" : -34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2015-11-05",
+			"PropertyDateTimeOffset" : "2005-12-03T07:17:08Z",
+			"PropertyDuration" : "P0DT0H0M9S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789dddfff",
+			"PropertyTimeOfDay" : "23:49:14"
+		}, {
+			"PropertyInt16" : 0,
+			"PropertyString" : "",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : 0,
+			"PropertyInt32" : 0,
+			"PropertyInt64" : 0,
+			"PropertySingle" : 0.00000000E+00,
+			"PropertyDouble" : 0.0000000000000000E+00,
+			"PropertyDecimal" : 0,
+			"PropertyBinary" : "",
+			"PropertyDate" : "1970-01-01",
+			"PropertyDateTimeOffset" : "2005-12-03T00:00:00Z",
+			"PropertyDuration" : "P0DT0H0M0S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789cccddd",
+			"PropertyTimeOfDay" : "00:01:01"
+		}
+	]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/ESAllPrimWithODataAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/ESAllPrimWithODataAnnotations.json b/lib/server-test/src/test/resources/ESAllPrimWithODataAnnotations.json
new file mode 100644
index 0000000..ce3ae40
--- /dev/null
+++ b/lib/server-test/src/test/resources/ESAllPrimWithODataAnnotations.json
@@ -0,0 +1,59 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim",
+	"@odata.count" : 3,
+	"@odata.nextLink" : "http://localhost:8080/nextLink",
+	"@odata.deltaLink" : "http://localhost:8080/deltaLink",
+	"value" : [{
+			"PropertyInt16" : 32767,
+			"PropertyString" : "First Resource - positive values",
+			"PropertyBoolean" : true,
+			"PropertyByte" : 255,
+			"PropertySByte" : 127,
+			"PropertyInt32" : 2147483647,
+			"PropertyInt64" : 9223372036854775807,
+			"PropertySingle" : 1.79000000E+20,
+			"PropertyDouble" : -1.7900000000000000E+19,
+			"PropertyDecimal" : 34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2012-12-03",
+			"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+			"PropertyDuration" : "P0DT0H0M6S",
+			"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+			"PropertyTimeOfDay" : "03:26:05"
+		}, {
+			"PropertyInt16" : -32768,
+			"PropertyString" : "Second Resource - negative values",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : -128,
+			"PropertyInt32" : -2147483648,
+			"PropertyInt64" : -9223372036854775808,
+			"PropertySingle" : -1.79000000E+08,
+			"PropertyDouble" : -1.7900000000000000E+05,
+			"PropertyDecimal" : -34,
+			"PropertyBinary" : "ASNFZ4mrze8=",
+			"PropertyDate" : "2015-11-05",
+			"PropertyDateTimeOffset" : "2005-12-03T07:17:08Z",
+			"PropertyDuration" : "P0DT0H0M9S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789dddfff",
+			"PropertyTimeOfDay" : "23:49:14"
+		}, {
+			"PropertyInt16" : 0,
+			"PropertyString" : "",
+			"PropertyBoolean" : false,
+			"PropertyByte" : 0,
+			"PropertySByte" : 0,
+			"PropertyInt32" : 0,
+			"PropertyInt64" : 0,
+			"PropertySingle" : 0.00000000E+00,
+			"PropertyDouble" : 0.0000000000000000E+00,
+			"PropertyDecimal" : 0,
+			"PropertyBinary" : "",
+			"PropertyDate" : "1970-01-01",
+			"PropertyDateTimeOffset" : "2005-12-03T00:00:00Z",
+			"PropertyDuration" : "P0DT0H0M0S",
+			"PropertyGuid" : "76543201-23ab-cdef-0123-456789cccddd",
+			"PropertyTimeOfDay" : "00:01:01"
+		}
+	]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json
new file mode 100644
index 0000000..edcc3ad
--- /dev/null
+++ b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithCustomAnnotations.json
@@ -0,0 +1,25 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim/$entity",
+	"PropertyInt16" : 32767,
+	"PropertyString" : "First Resource - positive values",
+	"PropertyBoolean" : true,
+	"PropertyByte" : 255,
+	"PropertySByte" : 127,
+	"PropertyInt32" : 2147483647,
+	"PropertyInt64" : 9223372036854775807,
+	"PropertySingle" : 1.79000000E+20,
+	"PropertyDouble" : -1.7900000000000000E+19,
+	"PropertyDecimal" : 34,
+	"PropertyBinary" : "ASNFZ4mrze8=",
+	"PropertyDate" : "2012-12-03",
+	"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+	"PropertyDuration" : "P0DT0H0M6S",
+	"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+	"PropertyTimeOfDay" : "03:26:05",
+	"NavPropertyETTwoPrimMany@custom.annotation" : "customValue",
+	"NavPropertyETTwoPrimMany" : [{
+			"PropertyInt16" : -365,
+			"PropertyString" : "Test String2"
+		}
+	]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json
new file mode 100644
index 0000000..4cbf650
--- /dev/null
+++ b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimManyWithODataAnnotations.json
@@ -0,0 +1,27 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim/$entity",
+	"PropertyInt16" : 32767,
+	"PropertyString" : "First Resource - positive values",
+	"PropertyBoolean" : true,
+	"PropertyByte" : 255,
+	"PropertySByte" : 127,
+	"PropertyInt32" : 2147483647,
+	"PropertyInt64" : 9223372036854775807,
+	"PropertySingle" : 1.79000000E+20,
+	"PropertyDouble" : -1.7900000000000000E+19,
+	"PropertyDecimal" : 34,
+	"PropertyBinary" : "ASNFZ4mrze8=",
+	"PropertyDate" : "2012-12-03",
+	"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+	"PropertyDuration" : "P0DT0H0M6S",
+	"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+	"PropertyTimeOfDay" : "03:26:05",
+	"NavPropertyETTwoPrimMany@odata.context" : "http://localhost:8080/context",
+	"NavPropertyETTwoPrimMany@odata.count" : 12,
+	"NavPropertyETTwoPrimMany@odata.nextLink" : "http://localhost:8080/nextLink",
+	"NavPropertyETTwoPrimMany" : [{
+			"PropertyInt16" : -365,
+			"PropertyString" : "Test String2"
+		}
+	]
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json
new file mode 100644
index 0000000..85c55e7
--- /dev/null
+++ b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithCustomAnnotations.json
@@ -0,0 +1,24 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim/$entity",
+	"PropertyInt16" : 32767,
+	"PropertyString" : "First Resource - positive values",
+	"PropertyBoolean" : true,
+	"PropertyByte" : 255,
+	"PropertySByte" : 127,
+	"PropertyInt32" : 2147483647,
+	"PropertyInt64" : 9223372036854775807,
+	"PropertySingle" : 1.79000000E+20,
+	"PropertyDouble" : -1.7900000000000000E+19,
+	"PropertyDecimal" : 34,
+	"PropertyBinary" : "ASNFZ4mrze8=",
+	"PropertyDate" : "2012-12-03",
+	"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+	"PropertyDuration" : "P0DT0H0M6S",
+	"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+	"PropertyTimeOfDay" : "03:26:05",
+	"NavPropertyETTwoPrimOne@custom.annotation" : "customValue",
+	"NavPropertyETTwoPrimOne" : {
+		"PropertyInt16" : 32767,
+		"PropertyString" : "Test String4"
+	}
+}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b6c1e347/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json
new file mode 100644
index 0000000..e778f58
--- /dev/null
+++ b/lib/server-test/src/test/resources/EntityESAllPrimExpandedNavPropertyETTwoPrimOneWithODataAnnotations.json
@@ -0,0 +1,26 @@
+{
+	"@odata.context" : "$metadata#ESAllPrim/$entity",
+	"PropertyInt16" : 32767,
+	"PropertyString" : "First Resource - positive values",
+	"PropertyBoolean" : true,
+	"PropertyByte" : 255,
+	"PropertySByte" : 127,
+	"PropertyInt32" : 2147483647,
+	"PropertyInt64" : 9223372036854775807,
+	"PropertySingle" : 1.79000000E+20,
+	"PropertyDouble" : -1.7900000000000000E+19,
+	"PropertyDecimal" : 34,
+	"PropertyBinary" : "ASNFZ4mrze8=",
+	"PropertyDate" : "2012-12-03",
+	"PropertyDateTimeOffset" : "2012-12-03T07:16:23Z",
+	"PropertyDuration" : "P0DT0H0M6S",
+	"PropertyGuid" : "01234567-89ab-cdef-0123-456789abcdef",
+	"PropertyTimeOfDay" : "03:26:05",
+	"NavPropertyETTwoPrimOne@odata.context" : "http://localhost:8080/context",
+	"NavPropertyETTwoPrimOne@odata.count" : 12,
+	"NavPropertyETTwoPrimOne@odata.nextLink" : "http://localhost:8080/nextLink",
+	"NavPropertyETTwoPrimOne" : {
+		"PropertyInt16" : 32767,
+		"PropertyString" : "Test String4"
+	}
+}