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/07/03 14:21:23 UTC

olingo-odata4 git commit: [OLINGO-570] JsonMetadatadocument serializer part2

Repository: olingo-odata4
Updated Branches:
  refs/heads/jsonMetadata 99c201eaf -> 9167e6eb1


[OLINGO-570] JsonMetadatadocument serializer part2


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

Branch: refs/heads/jsonMetadata
Commit: 9167e6eb1d89ecd4f67ce3499f2f3be615e77e98
Parents: 99c201e
Author: Christian Amend <ch...@sap.com>
Authored: Fri Jul 3 14:20:05 2015 +0200
Committer: Christian Amend <ch...@sap.com>
Committed: Fri Jul 3 14:20:40 2015 +0200

----------------------------------------------------------------------
 .../json/MetadataDocumentJsonSerializer.java    | 519 ++++++++++++++-----
 .../MetadataDocumentJsonSerializerTest.java     | 222 --------
 .../json/MetadataDocumentJsonTest.java          | 438 ++++++++++++++++
 3 files changed, 838 insertions(+), 341 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9167e6eb/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializer.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializer.java b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializer.java
index 4cf9abb..de8bbd0 100644
--- a/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializer.java
+++ b/lib/server-core/src/main/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializer.java
@@ -22,6 +22,7 @@ package org.apache.olingo.server.core.serializer.json;
 import com.fasterxml.jackson.core.JsonGenerator;
 import org.apache.olingo.commons.api.edm.*;
 import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.core.edm.primitivetype.EdmPrimitiveTypeFactory;
 import org.apache.olingo.server.api.ServiceMetadata;
 import org.apache.olingo.server.api.edmx.EdmxReference;
 import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
@@ -75,8 +76,9 @@ public class MetadataDocumentJsonSerializer {
     private static final String CONSTANT_TARGET = "target";
     private static final String CONSTANT_PROPERTIES = "properties";
     private static final String CONSTANT_OBJECT = "object";
+    private static final String CONSTANT_ARRAY = "array";
+    private static final String CONSTANT_ITEMS = "items";
     private static final String CONSTANT_ABSTRACT = "abstract";
-    private static final String CONSTANT_BASE_TYPE = "baseType";
     private static final String CONSTANT_IS_UNICODE = "unicode";
     private static final String CONSTANT_DEFAULT_VALUE = "defaultValue";
     private static final String CONSTANT_PARTNER = "partner";
@@ -91,6 +93,18 @@ public class MetadataDocumentJsonSerializer {
     private static final String CONSTANT_ENTITY_TYPE = "entityType";
     private static final String CONSTANT_ENTITY_CONTAINER = "entityContainer";
     private static final String CONSTANT_EXTEND = "extend";
+    private static final String CONSTANT_BASE_TYPE_IDENTIFIER = "allOf";
+    private static final String CONSTANT_PROPERTY_BASE_TYPE_IDENTIFIER = "anyOf";
+    private static final String CONSTANT_STRING = "string";
+    private static final String CONSTANT_NUMBER = "number";
+    private static final String CONSTANT_MINIMUM = "minimum";
+    private static final String CONSTANT_MAXIMUM = "maximum";
+    private static final String CONSTANT_MULTIPLE_OF = "multipleOf";
+    private static final String CONSTANT_PATTERN_IDENTIFIER = "pattern";
+    private static final String CONSTANT_BOOLEAN = "boolean";
+    private static final String CONSTANT_DATE_TIME_PATTERN_1 = "(^[^.]*$|[.][0-9]{1,precision}$)";
+    private static final String CONSTANT_DATE_TIME_PATTERN_2 = "^[^.]*$";
+
 
     public MetadataDocumentJsonSerializer(final ServiceMetadata serviceMetadata) {
         this.serviceMetadata = serviceMetadata;
@@ -151,24 +165,26 @@ public class MetadataDocumentJsonSerializer {
 
     private void appendTypeDefinitions(final JsonGenerator gen, final List<EdmTypeDefinition> typeDefinitions)
             throws IOException {
-        for (EdmTypeDefinition definition : typeDefinitions) {
-            gen.writeFieldName(getAliasedFullQualifiedName(definition, false));
-            gen.writeStartObject();
-            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER,
-                    CONSTANT_DEFINITION_REFERENCE + getFullQualifiedName(definition.getUnderlyingType(), false));
+        if(!typeDefinitions.isEmpty()) {
+            for (EdmTypeDefinition definition : typeDefinitions) {
+                gen.writeFieldName(getAliasedFullQualifiedName(definition, false));
+                gen.writeStartObject();
+                gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER,
+                        CONSTANT_DEFINITION_REFERENCE + getFullQualifiedName(definition.getUnderlyingType(), false));
 
-            if (definition.getMaxLength() != null) {
-                gen.writeNumberField(CONSTANT_MAX_LENGTH, definition.getMaxLength());
-            }
+                if (definition.getMaxLength() != null) {
+                    gen.writeNumberField(CONSTANT_MAX_LENGTH, definition.getMaxLength());
+                }
 
-            if (definition.getPrecision() != null) {
-                gen.writeNumberField(CONSTANT_PRECISION, definition.getPrecision());
-            }
+                if (definition.getPrecision() != null) {
+                    gen.writeNumberField(CONSTANT_PRECISION, definition.getPrecision());
+                }
 
-            if (definition.getScale() != null) {
-                gen.writeNumberField(CONSTANT_SCALE, definition.getScale());
+                if (definition.getScale() != null) {
+                    gen.writeNumberField(CONSTANT_SCALE, definition.getScale());
+                }
+                gen.writeEndObject();
             }
-            gen.writeEndObject();
         }
     }
 
@@ -229,7 +245,7 @@ public class MetadataDocumentJsonSerializer {
             } else {
                 returnTypeFqnString = getAliasedFullQualifiedName(returnType.getType(), returnType.isCollection());
             }
-            gen.writeStringField(CONSTANT_TYPE,returnTypeFqnString);
+            gen.writeStringField(CONSTANT_TYPE, returnTypeFqnString);
             appendReturnTypeFacets(gen, returnType);
             gen.writeEndObject();
         }
@@ -321,69 +337,75 @@ public class MetadataDocumentJsonSerializer {
 
     private void appendFunctionImports(final JsonGenerator gen, final List<EdmFunctionImport> functionImports,
                                        final String containerNamespace) throws IOException {
-        gen.writeFieldName(CONSTANT_FUNCTION_IMPORTS);
-        gen.writeStartObject();
-        for (EdmFunctionImport functionImport : functionImports) {
-            gen.writeFieldName(functionImport.getName());
+        if(!functionImports.isEmpty()) {
+            gen.writeFieldName(CONSTANT_FUNCTION_IMPORTS);
             gen.writeStartObject();
-            String functionFQNString;
-            FullQualifiedName functionFqn = functionImport.getFunctionFqn();
-            if (namespaceToAlias.get(functionFqn.getNamespace()) != null) {
-                functionFQNString = namespaceToAlias.get(functionFqn.getNamespace()) + "." + functionFqn.getName();
-            } else {
-                functionFQNString = functionFqn.getFullQualifiedNameAsString();
-            }
-            gen.writeStringField(CONSTANT_FUNCTION_IDENTIFIER,functionFQNString);
-            EdmEntitySet returnedEntitySet = functionImport.getReturnedEntitySet();
-            if (returnedEntitySet != null) {
-                gen.writeStringField(CONSTANT_ENTITY_SET, containerNamespace + "." + returnedEntitySet.getName());
-            }
-            if (functionImport.isIncludeInServiceDocument()) {
-                gen.writeBooleanField(CONSTANT_IS_INCLUDED_IN_SERVICE_DOCUMENT,
-                        functionImport.isIncludeInServiceDocument());
+            for (EdmFunctionImport functionImport : functionImports) {
+                gen.writeFieldName(functionImport.getName());
+                gen.writeStartObject();
+                String functionFQNString;
+                FullQualifiedName functionFqn = functionImport.getFunctionFqn();
+                if (namespaceToAlias.get(functionFqn.getNamespace()) != null) {
+                    functionFQNString = namespaceToAlias.get(functionFqn.getNamespace()) + "." + functionFqn.getName();
+                } else {
+                    functionFQNString = functionFqn.getFullQualifiedNameAsString();
+                }
+                gen.writeStringField(CONSTANT_FUNCTION_IDENTIFIER, functionFQNString);
+                EdmEntitySet returnedEntitySet = functionImport.getReturnedEntitySet();
+                if (returnedEntitySet != null) {
+                    gen.writeStringField(CONSTANT_ENTITY_SET, containerNamespace + "." + returnedEntitySet.getName());
+                }
+                if (functionImport.isIncludeInServiceDocument()) {
+                    gen.writeBooleanField(CONSTANT_IS_INCLUDED_IN_SERVICE_DOCUMENT,
+                            functionImport.isIncludeInServiceDocument());
+                }
+                gen.writeEndObject();
             }
             gen.writeEndObject();
         }
-        gen.writeEndObject();
     }
 
     private void appendActionImports(final JsonGenerator gen, final List<EdmActionImport> actionImports)
             throws IOException {
-        gen.writeFieldName(CONSTANT_ACTION_IMPORTS);
-        gen.writeStartObject();
-        for (EdmActionImport actionImport : actionImports) {
-            gen.writeFieldName(actionImport.getName());
+        if(!actionImports.isEmpty()) {
+            gen.writeFieldName(CONSTANT_ACTION_IMPORTS);
             gen.writeStartObject();
-            gen.writeStringField(CONSTANT_ACTION_IDENTIFIER,
-                    getAliasedFullQualifiedName(actionImport.getUnboundAction(), false));
+            for (EdmActionImport actionImport : actionImports) {
+                gen.writeFieldName(actionImport.getName());
+                gen.writeStartObject();
+                gen.writeStringField(CONSTANT_ACTION_IDENTIFIER,
+                        getAliasedFullQualifiedName(actionImport.getUnboundAction(), false));
+                gen.writeEndObject();
+            }
             gen.writeEndObject();
         }
-        gen.writeEndObject();
     }
 
     private void appendSingletons(final JsonGenerator gen, final List<EdmSingleton> singletons)
             throws IOException {
-        gen.writeFieldName(CONSTANT_SINGLETONS);
-        gen.writeStartObject();
-        for (EdmSingleton singleton : singletons) {
-            gen.writeFieldName(singleton.getName());
+        if(!singletons.isEmpty()) {
+            gen.writeFieldName(CONSTANT_SINGLETONS);
             gen.writeStartObject();
-            gen.writeStringField(CONSTANT_TYPE, getAliasedFullQualifiedName(singleton.getEntityType(), false));
-            appendNavigationPropertyBindings(gen, singleton);
+            for (EdmSingleton singleton : singletons) {
+                gen.writeFieldName(singleton.getName());
+                gen.writeStartObject();
+                gen.writeStringField(CONSTANT_TYPE, getAliasedFullQualifiedName(singleton.getEntityType(), false));
+                appendNavigationPropertyBindings(gen, singleton);
+                gen.writeEndObject();
+            }
             gen.writeEndObject();
         }
-        gen.writeEndObject();
     }
 
     private void appendNavigationPropertyBindings(final JsonGenerator gen, final EdmBindingTarget bindingTarget)
             throws IOException {
-        if (bindingTarget.getNavigationPropertyBindings() != null) {
+        if (!bindingTarget.getNavigationPropertyBindings().isEmpty()) {
             gen.writeFieldName(CONSTANT_NAVIGATION_PROPERTY_BINDINGS);
             gen.writeStartObject();
             for (EdmNavigationPropertyBinding binding : bindingTarget.getNavigationPropertyBindings()) {
                 gen.writeFieldName(binding.getPath());
                 gen.writeStartObject();
-                gen.writeStringField(CONSTANT_TARGET,binding.getTarget());
+                gen.writeStringField(CONSTANT_TARGET, binding.getTarget());
                 gen.writeEndObject();
             }
             gen.writeEndObject();
@@ -414,15 +436,20 @@ public class MetadataDocumentJsonSerializer {
             gen.writeFieldName(getFullQualifiedName(complexType, false));
             gen.writeStartObject();
             gen.writeStringField(CONSTANT_TYPE, CONSTANT_OBJECT);
+
             if (complexType.getBaseType() != null) {
-                gen.writeStringField(CONSTANT_BASE_TYPE,
-                        getAliasedFullQualifiedName(complexType.getBaseType(), false));
+                gen.writeFieldName(CONSTANT_BASE_TYPE_IDENTIFIER);
+                gen.writeStartArray();
+                gen.writeStartObject();
+                gen.writeStringField( CONSTANT_REFERENCE_IDENTIFIER , CONSTANT_DEFINITION_REFERENCE +
+                                getAliasedFullQualifiedName(complexType.getBaseType(), false));
+                gen.writeEndObject();
+                gen.writeEndArray();
             }
             if (complexType.isAbstract()) {
                 gen.writeBooleanField(CONSTANT_ABSTRACT, complexType.isAbstract());
             }
-            appendProperties(gen, complexType);
-            appendNavigationProperties(gen, complexType);
+            appendCombinedProperties(gen, complexType);
             gen.writeEndObject();
         }
     }
@@ -437,7 +464,13 @@ public class MetadataDocumentJsonSerializer {
                 gen.writeBooleanField(CONSTANT_HAS_STREAM, entityType.hasStream());
             }
             if (entityType.getBaseType() != null) {
-                gen.writeStringField(CONSTANT_BASE_TYPE, getAliasedFullQualifiedName(entityType.getBaseType(), false));
+                gen.writeFieldName(CONSTANT_BASE_TYPE_IDENTIFIER);
+                gen.writeStartArray();
+                gen.writeStartObject();
+                gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER , CONSTANT_DEFINITION_REFERENCE +
+                        getAliasedFullQualifiedName(entityType.getBaseType(), false));
+                gen.writeEndObject();
+                gen.writeEndArray();
             }
             if (entityType.isAbstract()) {
                 gen.writeBooleanField(CONSTANT_ABSTRACT, entityType.isAbstract());
@@ -446,103 +479,322 @@ public class MetadataDocumentJsonSerializer {
                 gen.writeBooleanField(CONSTANT_OPEN_TYPE,entityType.isOpenType());
             }
             appendKey(gen, entityType);
-            appendProperties(gen, entityType);
-            appendNavigationProperties(gen, entityType);
+            appendCombinedProperties(gen, entityType);
             gen.writeEndObject();
         }
     }
 
-    private void appendNavigationProperties(final JsonGenerator gen, final EdmStructuredType type)
-            throws IOException {
+    private void appendCombinedProperties(final JsonGenerator gen, final EdmStructuredType type)
+            throws IOException{
         gen.writeFieldName(CONSTANT_PROPERTIES);
         gen.writeStartObject();
+        appendProperties(gen, type);
+        appendNavigationProperties(gen, type);
+        gen.writeEndObject();
+    }
+
+    private void appendNavigationProperties(final JsonGenerator gen, final EdmStructuredType type)
+            throws IOException {
         List<String> navigationPropertyNames = new ArrayList<String>(type.getNavigationPropertyNames());
         if (type.getBaseType() != null) {
             navigationPropertyNames.removeAll(type.getBaseType().getNavigationPropertyNames());
         }
-        for (String navigationPropertyName : navigationPropertyNames) {
-            gen.writeFieldName(navigationPropertyName);
-            gen.writeStartObject();
-            EdmNavigationProperty navigationProperty = type.getNavigationProperty(navigationPropertyName);
-            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
-                    getAliasedFullQualifiedName(navigationProperty.getType(), false));
-            if (navigationProperty.isNullable() == false) {
-                gen.writeBooleanField(CONSTANT_NULLABLE, navigationProperty.isNullable());
-            }
-            gen.writeFieldName(CONSTANT_RELATIONSHIP);
-            gen.writeStartObject();
-            if (navigationProperty.getPartner() != null) {
-                EdmNavigationProperty partner = navigationProperty.getPartner();
-                gen.writeStringField(CONSTANT_PARTNER, partner.getName());
-            }
-            if (navigationProperty.containsTarget()) {
-                gen.writeBooleanField(CONSTANT_CONTAINS_TARGET, navigationProperty.containsTarget());
-            }
-
-            if (navigationProperty.getReferentialConstraints() != null) {
-                gen.writeFieldName(CONSTANT_REFERENTIAL_CONSTRAINTS);
+        if(!navigationPropertyNames.isEmpty()) {
+            for (String navigationPropertyName : navigationPropertyNames) {
+                gen.writeFieldName(navigationPropertyName);
                 gen.writeStartObject();
-                for (EdmReferentialConstraint constraint : navigationProperty.getReferentialConstraints()) {
-                    gen.writeFieldName(constraint.getPropertyName());
+                EdmNavigationProperty navigationProperty = type.getNavigationProperty(navigationPropertyName);
+                if(!navigationProperty.isNullable()) {
+                    if (!navigationProperty.isCollection()) {
+                        gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                getAliasedFullQualifiedName(navigationProperty.getType(), false));
+                    } else {
+                        gen.writeStringField(CONSTANT_TYPE, CONSTANT_ARRAY);
+                        gen.writeFieldName(CONSTANT_ITEMS);
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                getAliasedFullQualifiedName(navigationProperty.getType(), false));
+                        gen.writeEndObject();
+                    }
+                }else{
+                    if (!navigationProperty.isCollection()) {
+                        gen.writeFieldName(CONSTANT_PROPERTY_BASE_TYPE_IDENTIFIER);
+                        gen.writeStartArray();
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                getAliasedFullQualifiedName(navigationProperty.getType(), false));
+                        gen.writeEndObject();
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_TYPE, null);
+                        gen.writeEndObject();
+                        gen.writeEndArray();
+                    }else{
+                        gen.writeStringField(CONSTANT_TYPE, CONSTANT_ARRAY);
+                        gen.writeFieldName(CONSTANT_ITEMS);
+                        gen.writeStartObject();
+                        gen.writeFieldName(CONSTANT_PROPERTY_BASE_TYPE_IDENTIFIER);
+                        gen.writeStartArray();
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                getAliasedFullQualifiedName(navigationProperty.getType(), false));
+                        gen.writeEndObject();
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_TYPE, null);
+                        gen.writeEndObject();
+                        gen.writeEndArray();
+                        gen.writeEndObject();
+                    }
+                }
+                gen.writeFieldName(CONSTANT_RELATIONSHIP);
+                gen.writeStartObject();
+                if (navigationProperty.getPartner() != null) {
+                    EdmNavigationProperty partner = navigationProperty.getPartner();
+                    gen.writeStringField(CONSTANT_PARTNER, partner.getName());
+                }
+                if (navigationProperty.containsTarget()) {
+                    gen.writeBooleanField(CONSTANT_CONTAINS_TARGET, navigationProperty.containsTarget());
+                }
+
+                if (navigationProperty.getReferentialConstraints() != null) {
+                    gen.writeFieldName(CONSTANT_REFERENTIAL_CONSTRAINTS);
                     gen.writeStartObject();
-                    gen.writeStringField(CONSTANT_REFERENCED_PROPERTY, constraint.getReferencedPropertyName());
+                    for (EdmReferentialConstraint constraint : navigationProperty.getReferentialConstraints()) {
+                        gen.writeFieldName(constraint.getPropertyName());
+                        gen.writeStartObject();
+                        gen.writeStringField(CONSTANT_REFERENCED_PROPERTY, constraint.getReferencedPropertyName());
+                        gen.writeEndObject();
+                    }
                     gen.writeEndObject();
                 }
                 gen.writeEndObject();
+                gen.writeEndObject();
             }
-            gen.writeEndObject();
-            gen.writeEndObject();
         }
-        gen.writeEndObject();
     }
 
     private void appendProperties(final JsonGenerator gen, final EdmStructuredType type) throws IOException {
-        gen.writeFieldName(CONSTANT_PROPERTIES);
-        gen.writeStartObject();
         List<String> propertyNames = new ArrayList<String>(type.getPropertyNames());
         if (type.getBaseType() != null) {
             propertyNames.removeAll(type.getBaseType().getPropertyNames());
         }
-        for (String propertyName : propertyNames) {
-            EdmProperty property = type.getStructuralProperty(propertyName);
-            gen.writeFieldName(propertyName);
-            gen.writeStartObject();
-            String fqnString;
-            if (property.isPrimitive()) {
-                fqnString = getFullQualifiedName(property.getType(), property.isCollection());
-            } else {
-                fqnString = getAliasedFullQualifiedName(property.getType(), property.isCollection());
-            }
-            gen.writeStringField(CONSTANT_TYPE,fqnString);
+        if(!propertyNames.isEmpty()) {
+            for (String propertyName : propertyNames) {
+                EdmProperty property = type.getStructuralProperty(propertyName);
+                gen.writeFieldName(propertyName);
+                gen.writeStartObject();
+                if(!property.isNullable()) {
+                    if (!property.isCollection()) {
+                        if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.String).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_STRING);
+                        }else if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Decimal).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_NUMBER);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Boolean).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_BOOLEAN);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.DateTimeOffset).getName())||
+                        property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Duration).getName())||
+                                property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                        .getInstance(EdmPrimitiveTypeKind.TimeOfDay).getName())){
+                            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                    getAliasedFullQualifiedName(property.getType(), false));
+                        }else {
+                            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                    getAliasedFullQualifiedName(property.getType(), false));
+                        }
+                        appendPropertyFacets(gen,property);
+                    } else {
+                        gen.writeStringField(CONSTANT_TYPE, CONSTANT_ARRAY);
+                        gen.writeFieldName(CONSTANT_ITEMS);
+                        gen.writeStartObject();
+                        if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.String).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_STRING);
+                        }else if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Decimal).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_NUMBER);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Boolean).getName())){
+                            gen.writeStringField(CONSTANT_TYPE,CONSTANT_BOOLEAN);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.DateTimeOffset).getName())||
+                                property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                        .getInstance(EdmPrimitiveTypeKind.Duration).getName())||
+                                property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                        .getInstance(EdmPrimitiveTypeKind.TimeOfDay).getName())){
+                            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                    getAliasedFullQualifiedName(property.getType(), false));
+                        }else {
+                            gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                    getAliasedFullQualifiedName(property.getType(), false));
+                        }
+                        appendPropertyFacets(gen,property);
+                        gen.writeEndObject();
+                    }
+                }else{
+                    if(!property.isCollection()){
+                        if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.String).getName())) {
+                            gen.writeFieldName(CONSTANT_TYPE);
+                            gen.writeStartArray();
+                            gen.writeString(CONSTANT_STRING);
+                            gen.writeNull();
+                            gen.writeEndArray();
+                            appendPropertyFacets(gen, property);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Boolean).getName())){
+                            gen.writeFieldName(CONSTANT_TYPE);
+                            gen.writeStartArray();
+                            gen.writeString(CONSTANT_BOOLEAN);
+                            gen.writeNull();
+                            gen.writeEndArray();
+                            appendPropertyFacets(gen,property);
+                        }else {
+                            gen.writeFieldName(CONSTANT_PROPERTY_BASE_TYPE_IDENTIFIER);
+                            gen.writeStartArray();
+                            if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                    .getInstance(EdmPrimitiveTypeKind.Decimal).getName())) {
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_TYPE, CONSTANT_NUMBER);
+                                appendPropertyFacets(gen, property);
+                                gen.writeEndObject();
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_TYPE,null);
+                                gen.writeEndObject();
+                            } else {
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                        getAliasedFullQualifiedName(property.getType(), false));
+                                gen.writeEndObject();
+                                gen.writeStartObject();
+                                if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                        .getInstance(EdmPrimitiveTypeKind.DateTimeOffset).getName()) ||
+                                        property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                                .getInstance(EdmPrimitiveTypeKind.Duration).getName()) ||
+                                        property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                                .getInstance(EdmPrimitiveTypeKind.TimeOfDay).getName())) {
+                                    if (property.getPrecision()==null||property.getPrecision() == 0) {
+                                        gen.writeStringField(CONSTANT_PATTERN_IDENTIFIER,
+                                                    CONSTANT_DATE_TIME_PATTERN_2);
+                                    } else {
+                                            gen.writeStringField(CONSTANT_PATTERN_IDENTIFIER,
+                                                    CONSTANT_DATE_TIME_PATTERN_1.replace("precision",
+                                                            String.valueOf(property.getPrecision())));
+                                    }
+                                } else {
+                                    gen.writeStringField(CONSTANT_TYPE, null);
+                                }
+                                appendPropertyFacets(gen, property);
+                                gen.writeEndObject();
+                            }
+                            gen.writeEndArray();
+                        }
 
-            if (property.isNullable() == false) {
-                gen.writeBooleanField(CONSTANT_NULLABLE, property.isNullable());
+                    }else{
+                        gen.writeStringField(CONSTANT_TYPE, CONSTANT_ARRAY);
+                        gen.writeFieldName(CONSTANT_ITEMS);
+                        gen.writeStartObject();
+                        if(property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.String).getName())) {
+                            gen.writeFieldName(CONSTANT_TYPE);
+                            gen.writeStartArray();
+                            gen.writeString(CONSTANT_STRING);
+                            gen.writeNull();
+                            gen.writeEndArray();
+                            appendPropertyFacets(gen, property);
+                        }else if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                .getInstance(EdmPrimitiveTypeKind.Boolean).getName())){
+                            gen.writeFieldName(CONSTANT_TYPE);
+                            gen.writeStartArray();
+                            gen.writeString(CONSTANT_BOOLEAN);
+                            gen.writeNull();
+                            gen.writeEndArray();
+                            appendPropertyFacets(gen,property);
+                        }else {
+                            gen.writeFieldName(CONSTANT_PROPERTY_BASE_TYPE_IDENTIFIER);
+                            gen.writeStartArray();
+                            if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                    .getInstance(EdmPrimitiveTypeKind.Decimal).getName())) {
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_TYPE, CONSTANT_NUMBER);
+                                appendPropertyFacets(gen, property);
+                                gen.writeEndObject();
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_TYPE,null);
+                                gen.writeEndObject();
+                            } else {
+                                gen.writeStartObject();
+                                gen.writeStringField(CONSTANT_REFERENCE_IDENTIFIER, CONSTANT_DEFINITION_REFERENCE +
+                                        getAliasedFullQualifiedName(property.getType(), false));
+                                gen.writeEndObject();
+                                gen.writeStartObject();
+                                if (property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                        .getInstance(EdmPrimitiveTypeKind.DateTimeOffset).getName()) ||
+                                        property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                                .getInstance(EdmPrimitiveTypeKind.Duration).getName()) ||
+                                        property.getType().getName().equals(EdmPrimitiveTypeFactory
+                                                .getInstance(EdmPrimitiveTypeKind.TimeOfDay).getName())) {
+                                    if(property.getPrecision()==null||property.getPrecision() == 0){
+                                        gen.writeStringField(CONSTANT_PATTERN_IDENTIFIER, CONSTANT_DATE_TIME_PATTERN_2);
+                                    }else{
+                                        gen.writeStringField(CONSTANT_PATTERN_IDENTIFIER,
+                                                CONSTANT_DATE_TIME_PATTERN_1.replace("precision",
+                                                        String.valueOf(property.getPrecision())));
+                                    }
+                                } else {
+                                    gen.writeStringField(CONSTANT_TYPE, null);
+                                }
+                                appendPropertyFacets(gen, property);
+                                gen.writeEndObject();
+                            }
+                            gen.writeEndArray();
+                        }
+                        gen.writeEndObject();
+                    }
+                }
+                gen.writeEndObject();
             }
+        }
+    }
 
-            if (property.isUnicode() == false) {
-                gen.writeBooleanField(CONSTANT_IS_UNICODE, property.isUnicode());
-            }
+    private void appendPropertyFacets(final JsonGenerator gen,EdmProperty property) throws IOException{
+        if (property.isUnicode() == false) {
+            gen.writeBooleanField(CONSTANT_IS_UNICODE, property.isUnicode());
+        }
 
-            if (property.getDefaultValue() != null) {
-                gen.writeStringField(CONSTANT_DEFAULT_VALUE, property.getDefaultValue());
-            }
+        if (property.getDefaultValue() != null) {
+            gen.writeStringField(CONSTANT_DEFAULT_VALUE, property.getDefaultValue());
+        }
 
-            if (property.getMaxLength() != null) {
-                gen.writeNumberField(CONSTANT_MAX_LENGTH, property.getMaxLength());
-            }
+        if (property.getMaxLength() != null) {
+            gen.writeNumberField(CONSTANT_MAX_LENGTH, property.getMaxLength());
+        }
 
-            if (property.getPrecision() != null) {
-                gen.writeNumberField(CONSTANT_PRECISION, property.getPrecision());
-            }
+        if (property.getScale() != null) {
+            gen.writeNumberField(CONSTANT_MULTIPLE_OF, getScale(property.getScale()));
 
-            if (property.getScale() != null) {
-                gen.writeNumberField(CONSTANT_SCALE, property.getScale());
+        }
+        if (property.getPrecision() != null) {
+            int scale;
+            if (property.getScale()!= null) {
+                scale=property.getScale();
+            }else{
+                scale=0;
+            }
+            int presicion = property.getPrecision();
+            if(presicion>scale) {
+                Double min = getMinimum(presicion, scale);
+                Double max = getMaximum(presicion, scale);
+                gen.writeNumberField(CONSTANT_MINIMUM, min);
+                gen.writeNumberField(CONSTANT_MAXIMUM, max);
             }
-            gen.writeEndObject();
         }
-        gen.writeEndObject();
     }
 
+
     private void appendKey(final JsonGenerator gen, final EdmEntityType entityType) throws IOException {
         List<EdmKeyPropertyRef> keyPropertyRefs = entityType.getKeyPropertyRefs();
         if (keyPropertyRefs != null && !keyPropertyRefs.isEmpty()) {
@@ -644,4 +896,33 @@ public class MetadataDocumentJsonSerializer {
         return isCollection ? "Collection(" + name + ")" : name;
     }
 
+    private Double getScale(int scale){
+        String temp;
+        if(scale!=0){
+            temp="1e-"+scale;
+        }else{
+            temp="1";
+        }
+        return Double.valueOf(temp);
+    }
+
+    private Double getMinimum(int precision , int scale){
+       return (-1)*getMaximum(precision,scale);
+    }
+
+    private Double getMaximum(int precision , int scale){
+        String temp="";
+        for(int counter=0;counter<(precision-scale);counter++){
+            temp=temp.concat("9");
+        }
+        if(scale==0){
+            return Double.valueOf(temp);
+        }else {
+            temp = temp.concat(".");
+            for (int counter = 0; counter < scale; counter++) {
+                temp = temp.concat("9");
+            }
+            return Double.valueOf(temp);
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9167e6eb/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializerTest.java
----------------------------------------------------------------------
diff --git a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializerTest.java b/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializerTest.java
deleted file mode 100644
index 3c4a38e..0000000
--- a/lib/server-core/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonSerializerTest.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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.serializer.json;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.olingo.commons.api.edm.Edm;
-import org.apache.olingo.commons.api.edm.EdmSchema;
-import org.apache.olingo.commons.api.format.ODataFormat;
-import org.apache.olingo.server.api.OData;
-import org.apache.olingo.server.api.ServiceMetadata;
-import org.apache.olingo.server.api.edmx.EdmxReference;
-import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
-import org.apache.olingo.server.api.edmx.EdmxReferenceIncludeAnnotation;
-import org.apache.olingo.server.api.serializer.ODataSerializer;
-import org.apache.olingo.server.api.serializer.SerializerException;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import java.io.InputStream;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MetadataDocumentJsonSerializerTest {
-
-    private static ODataSerializer serializer;
-
-    @BeforeClass
-    public static void init() throws SerializerException {
-        serializer = OData.newInstance().createSerializer(ODataFormat.JSON);
-    }
-
-    @Test
-    public void writeMetadataWithEmptyMockedEdm() throws Exception {
-        final Edm edm = mock(Edm.class);
-        ServiceMetadata metadata = mock(ServiceMetadata.class);
-        when(metadata.getEdm()).thenReturn(edm);
-        String resultString = IOUtils.toString(serializer.metadataDocument(metadata).getContent());
-        String expectedString = "{\n" +
-                "  \"$schema\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#\"\n" +
-                "}";
-
-        assertEquals(expectedString, resultString);
-    }
-
-    @Test
-    public void writeMetadataWithEmptySchema() throws Exception {
-        EdmSchema schema = mock(EdmSchema.class);
-        when(schema.getNamespace()).thenReturn("MyNamespace");
-        Edm edm = mock(Edm.class);
-        when(edm.getSchemas()).thenReturn(Arrays.asList(schema));
-        ServiceMetadata serviceMetadata = mock(ServiceMetadata.class);
-        when(serviceMetadata.getEdm()).thenReturn(edm);
-        InputStream metadata = serializer.metadataDocument(serviceMetadata).getContent();
-        String resultString = IOUtils.toString(metadata);
-        String expectedString = "{\n" +
-                "  \"$schema\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#\",\n" +
-                "  \"definitions\" : { },\n" +
-                "  \"schemas\" : {\n" +
-                "    \"MyNamespace\" : {\n" +
-                "      \"alias\" : null\n" +
-                "    }\n" +
-                "  }\n" +
-                "}";
-        assertNotNull(metadata);
-        assertEquals(expectedString, resultString);
-    }
-
-    @Test
-    public void writeEdmxWithLocalTestEdm() throws Exception {
-        List<EdmxReference> edmxReferences = new ArrayList<EdmxReference>();
-        EdmxReference reference = new EdmxReference(URI.create("http://example.com"));
-        edmxReferences.add(reference);
-
-        EdmxReference referenceWithInclude = new EdmxReference(
-                URI.create("http://localhost/odata/odata/v4.0/referenceWithInclude"));
-        EdmxReferenceInclude include = new EdmxReferenceInclude("Org.OData.Core.V1", "Core");
-        referenceWithInclude.addInclude(include);
-        edmxReferences.add(referenceWithInclude);
-
-        EdmxReference referenceWithTwoIncludes = new EdmxReference(
-                URI.create("http://localhost/odata/odata/v4.0/referenceWithTwoIncludes"));
-        referenceWithTwoIncludes.addInclude(new EdmxReferenceInclude("Org.OData.Core.2", "Core2"));
-        referenceWithTwoIncludes.addInclude(new EdmxReferenceInclude("Org.OData.Core.3", "Core3"));
-        edmxReferences.add(referenceWithTwoIncludes);
-
-        EdmxReference referenceWithIncludeAnnos = new EdmxReference(
-                URI.create("http://localhost/odata/odata/v4.0/referenceWithIncludeAnnos"));
-        referenceWithIncludeAnnos.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("TermNs.2", "Q.2", "TargetNS.2"));
-        referenceWithIncludeAnnos.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("TermNs.3", "Q.3", "TargetNS.3"));
-        edmxReferences.add(referenceWithIncludeAnnos);
-
-        EdmxReference referenceWithAll = new EdmxReference(
-                URI.create("http://localhost/odata/odata/v4.0/referenceWithAll"));
-        referenceWithAll.addInclude(new EdmxReferenceInclude("ReferenceWithAll.1", "Core1"));
-        referenceWithAll.addInclude(new EdmxReferenceInclude("ReferenceWithAll.2", "Core2"));
-        referenceWithAll.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermNs.4", "Q.4", "TargetNS.4"));
-        referenceWithAll.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermNs.5", "Q.5", "TargetNS.5"));
-        edmxReferences.add(referenceWithAll);
-
-        EdmxReference referenceWithAllAndNull = new EdmxReference(
-                URI.create("http://localhost/odata/odata/v4.0/referenceWithAllAndNull"));
-        referenceWithAllAndNull.addInclude(new EdmxReferenceInclude("referenceWithAllAndNull.1"));
-        referenceWithAllAndNull.addInclude(new EdmxReferenceInclude("referenceWithAllAndNull.2", null));
-        referenceWithAllAndNull.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermNs.4"));
-        referenceWithAllAndNull.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermAndNullNs.5", "Q.5", null));
-        referenceWithAllAndNull.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermAndNullNs.6", null, "TargetNS"));
-        referenceWithAllAndNull.addIncludeAnnotation(
-                new EdmxReferenceIncludeAnnotation("ReferenceWithAllTermAndNullNs.7", null, null));
-        edmxReferences.add(referenceWithAllAndNull);
-
-        ServiceMetadata serviceMetadata = mock(ServiceMetadata.class);
-        final Edm edm = mock(Edm.class);
-        when(serviceMetadata.getEdm()).thenReturn(edm);
-        when(serviceMetadata.getReferences()).thenReturn(edmxReferences);
-
-        InputStream metadata = serializer.metadataDocument(serviceMetadata).getContent();
-        assertNotNull(metadata);
-        final String resultString = IOUtils.toString(metadata);
-        String expectedString = "{\n" +
-                "  \"$schema\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#\",\n" +
-                "  \"references\" : {\n" +
-                "    \"http://example.com\" : { },\n" +
-                "    \"http://localhost/odata/odata/v4.0/referenceWithInclude\" : {\n" +
-                "      \"includes\" : {\n" +
-                "        \"Org.OData.Core.V1\" : {\n" +
-                "          \"alias\" : \"Core\"\n" +
-                "        }\n" +
-                "      }\n" +
-                "    },\n" +
-                "    \"http://localhost/odata/odata/v4.0/referenceWithTwoIncludes\" : {\n" +
-                "      \"includes\" : {\n" +
-                "        \"Org.OData.Core.2\" : {\n" +
-                "          \"alias\" : \"Core2\"\n" +
-                "        },\n" +
-                "        \"Org.OData.Core.3\" : {\n" +
-                "          \"alias\" : \"Core3\"\n" +
-                "        }\n" +
-                "      }\n" +
-                "    },\n" +
-                "    \"http://localhost/odata/odata/v4.0/referenceWithIncludeAnnos\" : {\n" +
-                "      \"includeAnnotations\" : [ {\n" +
-                "        \"termNamespace\" : \"TermNs.2\",\n" +
-                "        \"qualifier\" : \"Q.2\",\n" +
-                "        \"targetNamespace\" : \"TargetNS.2\"\n" +
-                "      }, {\n" +
-                "        \"termNamespace\" : \"TermNs.3\",\n" +
-                "        \"qualifier\" : \"Q.3\",\n" +
-                "        \"targetNamespace\" : \"TargetNS.3\"\n" +
-                "      } ]\n" +
-                "    },\n" +
-                "    \"http://localhost/odata/odata/v4.0/referenceWithAll\" : {\n" +
-                "      \"includes\" : {\n" +
-                "        \"ReferenceWithAll.1\" : {\n" +
-                "          \"alias\" : \"Core1\"\n" +
-                "        },\n" +
-                "        \"ReferenceWithAll.2\" : {\n" +
-                "          \"alias\" : \"Core2\"\n" +
-                "        }\n" +
-                "      },\n" +
-                "      \"includeAnnotations\" : [ {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermNs.4\",\n" +
-                "        \"qualifier\" : \"Q.4\",\n" +
-                "        \"targetNamespace\" : \"TargetNS.4\"\n" +
-                "      }, {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermNs.5\",\n" +
-                "        \"qualifier\" : \"Q.5\",\n" +
-                "        \"targetNamespace\" : \"TargetNS.5\"\n" +
-                "      } ]\n" +
-                "    },\n" +
-                "    \"http://localhost/odata/odata/v4.0/referenceWithAllAndNull\" : {\n" +
-                "      \"includes\" : {\n" +
-                "        \"referenceWithAllAndNull.1\" : { },\n" +
-                "        \"referenceWithAllAndNull.2\" : { }\n" +
-                "      },\n" +
-                "      \"includeAnnotations\" : [ {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermNs.4\"\n" +
-                "      }, {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermAndNullNs.5\",\n" +
-                "        \"qualifier\" : \"Q.5\"\n" +
-                "      }, {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermAndNullNs.6\",\n" +
-                "        \"targetNamespace\" : \"TargetNS\"\n" +
-                "      }, {\n" +
-                "        \"termNamespace\" : \"ReferenceWithAllTermAndNullNs.7\"\n" +
-                "      } ]\n" +
-                "    }\n" +
-                "  }\n" +
-                "}";
-
-        assertEquals(expectedString, resultString);
-    }
-}

http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/9167e6eb/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonTest.java
----------------------------------------------------------------------
diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonTest.java
new file mode 100644
index 0000000..d36bff2
--- /dev/null
+++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/MetadataDocumentJsonTest.java
@@ -0,0 +1,438 @@
+/*
+ * 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.serializer.json;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
+import org.apache.olingo.commons.api.format.ODataFormat;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.edmx.EdmxReference;
+import org.apache.olingo.server.api.edmx.EdmxReferenceInclude;
+import org.apache.olingo.server.tecsvc.provider.EdmTechProvider;
+import org.junit.Test;
+
+public class MetadataDocumentJsonTest {
+
+
+    private static final String CORE_VOCABULARY =
+            "http://docs.oasis-open.org/odata/odata/v4.0/cs02/vocabularies/Org.OData.Core.V1.xml";
+
+    @Test
+    public void writeMetadataWithTechnicalScenario() throws Exception {
+        final OData odata = OData.newInstance();
+        final List<EdmxReference> references = getEdmxReferences();
+        final ServiceMetadata serviceMetadata = odata.createServiceMetadata(
+                new EdmTechProvider(references), references);
+
+        final String metadata = IOUtils.toString(
+                odata.createSerializer(ODataFormat.JSON).metadataDocument(serviceMetadata).getContent());
+        assertNotNull(metadata);
+
+        String expectedString;
+        expectedString="\"$schema\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#\"";
+        assertThat(metadata, containsString(expectedString));
+
+
+        expectedString=
+        "\"olingo.odata.test1.ENString\" : {\n" +
+                "      \"enum\" : [ \"String1\", \"String2\", \"String3\" ],\n" +
+                "      \"String1@odata.value\" : \"1\",\n" +
+                "      \"String2@odata.value\" : \"2\",\n" +
+                "      \"String3@odata.value\" : \"4\"\n" +
+                "    }";
+        assertThat(metadata, containsString(expectedString));
+
+
+        expectedString="\"olingo.odata.test1.TDString\" : {\n" +"      \"$ref\" : \"http://docs.oasis-open.org/odata/" +
+                "odata-json-csdl/v4.0/edm.json#/definitions/Edm.String\",\n" +
+                "      \"maxLength\" : 15\n" +
+                "    }";
+
+        assertThat(metadata, containsString(expectedString));
+
+
+        expectedString=
+        " \"references\" : {\n" +
+                "    \"http://docs.oasis-open.org/odata/odata/v4.0/cs02/vocabularies/Org.OData.Core.V1.xml\" : {\n" +
+                "      \"includes\" : {\n" +
+                "        \"Org.OData.Core.V1\" : {\n" +
+                "          \"alias\" : \"Core\"\n" +
+                "        }\n" +
+                "      }\n" +
+                "    }\n" +
+                "  }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"singletons\" : {\n" +
+                "          \"SI\" : {\n" +
+                "            \"type\" : \"Namespace1_Alias.ETTwoPrim\"\n" +
+                "          },\n" +
+                "          \"SINav\" : {\n" +
+                "            \"type\" : \"Namespace1_Alias.ETTwoKeyNav\",\n" +
+                "            \"navigationPropertyBindings\" : {\n" +
+                "              \"NavPropertyETTwoKeyNavMany\" : {\n" +
+                "                \"target\" : \"ESTwoKeyNav\"\n" +
+                "              },\n" +
+                "              \"NavPropertyETTwoKeyNavOne\" : {\n" +
+                "                \"target\" : \"ESTwoKeyNav\"\n" +
+                "              },\n" +
+                "              \"NavPropertyETKeyNavOne\" : {\n" +
+                "                \"target\" : \"ESKeyNav\"\n" +
+                "              }\n" +
+                "            }\n" +
+                "          },\n" +
+                "          \"SIMedia\" : {\n" +
+                "            \"type\" : \"Namespace1_Alias.ETMedia\"\n" +
+                "          }\n" +
+                "        }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        " \"actionImports\" : {\n" +
+                "          \"AIRTString\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTString\"\n" +
+                "          },\n" +
+                "          \"AIRTCollStringTwoParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTCollStringTwoParam\"\n" +
+                "          },\n" +
+                "          \"AIRTCTTwoPrimParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTCTTwoPrimParam\"\n" +
+                "          },\n" +
+                "          \"AIRTCollCTTwoPrimParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTCollCTTwoPrimParam\"\n" +
+                "          },\n" +
+                "          \"AIRTETTwoKeyTwoPrimParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTETTwoKeyTwoPrimParam\"\n" +
+                "          },\n" +
+                "          \"AIRTCollETKeyNavParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTCollETKeyNavParam\"\n" +
+                "          },\n" +
+                "          \"AIRTESAllPrimParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTETAllPrimParam\"\n" +
+                "          },\n" +
+                "          \"AIRTCollESAllPrimParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTCollETAllPrimParam\"\n" +
+                "          },\n" +
+                "          \"AIRT\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UART\"\n" +
+                "          },\n" +
+                "          \"AIRTParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTParam\"\n" +
+                "          },\n" +
+                "          \"AIRTTwoParam\" : {\n" +
+                "            \"action\" : \"Namespace1_Alias.UARTTwoParam\"\n" +
+                "          }\n" +
+                "        }";
+        assertThat(metadata, containsString(expectedString));
+
+
+        expectedString=
+        "\"functionImports\" : {\n" +
+                "          \"FINRTInt16\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFNRTInt16\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FINInvisibleRTInt16\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFNRTInt16\"\n" +
+                "          },\n" +
+                "          \"FINInvisible2RTInt16\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFNRTInt16\"\n" +
+                "          },\n" +
+                "          \"FICRTETKeyNav\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTETKeyNav\"\n" +
+                "          },\n" +
+                "          \"FICRTESTwoKeyNav\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTETTwoKeyNav\",\n" +
+                "            \"entitySet\" : \"Namespace1_Alias.ESTwoKeyNav\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTETTwoKeyNavParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTETTwoKeyNavParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTStringTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTStringTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollStringTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollStringTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCTAllPrimTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCTAllPrimTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTESMixPrimCollCompTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTESMixPrimCollCompTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollETMixPrimCollCompTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollETMixPrimCollCompTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FINRTCollETMixPrimCollCompTwoParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFNRTCollETMixPrimCollCompTwoParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollCTTwoPrim\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollCTTwoPrim\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTESMedia\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTETMedia\",\n" +
+                "            \"entitySet\" : \"Namespace1_Alias.ESMedia\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollESMedia\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollETMedia\",\n" +
+                "            \"entitySet\" : \"Namespace1_Alias.ESMedia\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCTTwoPrimParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCTTwoPrimParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCTTwoPrim\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCTTwoPrim\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollString\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollString\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTString\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTString\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollESTwoKeyNavParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollETTwoKeyNavParam\",\n" +
+                "            \"entitySet\" : \"Namespace1_Alias.ESTwoKeyNav\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollCTTwoPrimParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollCTTwoPrimParam\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FINRTCollCTNavFiveProp\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFNRTCollCTNavFiveProp\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          },\n" +
+                "          \"FICRTCollESKeyNavContParam\" : {\n" +
+                "            \"function\" : \"Namespace1_Alias.UFCRTCollETKeyNavContParam\",\n" +
+                "            \"entitySet\" : \"Namespace1_Alias.ESKeyNavCont\",\n" +
+                "            \"includeInServiceDocument\" : true\n" +
+                "          }\n" +
+                "        }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"ESTwoPrim\" : {\n" +
+                "            \"entityType\" : \"Namespace1_Alias.ETTwoPrim\",\n" +
+                "            \"navigationPropertyBindings\" : {\n" +
+                "              \"NavPropertyETAllPrimOne\" : {\n" +
+                "                \"target\" : \"ESAllPrim\"\n" +
+                "              },\n" +
+                "              \"NavPropertyETAllPrimMany\" : {\n" +
+                "                \"target\" : \"ESAllPrim\"\n" +
+                "              }\n" +
+                "            }\n" +
+                "          }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        " {\n" +
+                "        \"name\" : \"UFCRTCollStringTwoParam\",\n" +
+                "        \"isComposable\" : true,\n" +
+                "        \"parameters\" : {\n" +
+                "          \"ParameterString\" : {\n" +
+                "            \"type\" : \"Edm.String\",\n" +
+                "            \"nullable\" : false\n" +
+                "          },\n" +
+                "          \"ParameterInt16\" : {\n" +
+                "            \"type\" : \"Edm.Int16\",\n" +
+                "            \"nullable\" : false\n" +
+                "          }\n" +
+                "        },\n" +
+                "        \"returnType\" : {\n" +
+                "          \"type\" : \"Collection(Edm.String)\",\n" +
+                "          \"nullable\" : false\n" +
+                "        }\n" +
+                "      }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "{\n" +
+                "        \"name\" : \"BAESTwoKeyNavRTESKeyNav\",\n" +
+                "        \"entitySetPath\" : \"BindingParam/NavPropertyETKeyNavMany\",\n" +
+                "        \"isBound\" : true,\n" +
+                "        \"parameters\" : {\n" +
+                "          \"ParameterETTwoKeyNav\" : {\n" +
+                "            \"type\" : \"Collection(Namespace1_Alias.ETTwoKeyNav)\",\n" +
+                "            \"nullable\" : false\n" +
+                "          }\n" +
+                "        },\n" +
+                "        \"returnType\" : {\n" +
+                "          \"type\" : \"Collection(Namespace1_Alias.ETKeyNav)\"\n" +
+                "        }\n" +
+                "      }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"olingo.odata.test1.CTBasePrimCompNav\" : {\n" +
+                "      \"type\" : \"object\",\n" +
+                "      \"allOf\" : [ {\n" +
+                "        \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.CTPrimComp\"\n" +
+                "      } ],\n" +
+                "      \"properties\" : {\n" +
+                "        \"NavPropertyETTwoKeyNavMany\" : {\n" +
+                "          \"type\" : \"array\",\n" +
+                "          \"items\" : {\n" +
+                "            \"anyOf\" : [ {\n" +
+                "              \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.ETTwoKeyNav\"\n" +
+                "            }, {\n" +
+                "              \"type\" : null\n" +
+                "            } ]\n" +
+                "          },\n" +
+                "          \"relationship\" : {\n" +
+                "            \"partner\" : \"NavPropertyETKeyNavOne\",\n" +
+                "            \"referentialConstraints\" : { }\n" +
+                "          }\n" +
+                "        },\n" +
+                "        \"NavPropertyETTwoKeyNavOne\" : {\n" +
+                "          \"anyOf\" : [ {\n" +
+                "            \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.ETTwoKeyNav\"\n" +
+                "          }, {\n" +
+                "            \"type\" : null\n" +
+                "          } ],\n" +
+                "          \"relationship\" : {\n" +
+                "            \"referentialConstraints\" : { }\n" +
+                "          }\n" +
+                "        },\n" +
+                "        \"NavPropertyETKeyNavOne\" : {\n" +
+                "          \"anyOf\" : [ {\n" +
+                "            \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.ETKeyNav\"\n" +
+                "          }, {\n" +
+                "            \"type\" : null\n" +
+                "          } ],\n" +
+                "          \"relationship\" : {\n" +
+                "            \"referentialConstraints\" : { }\n" +
+                "          }\n" +
+                "        },\n" +
+                "        \"NavPropertyETKeyNavMany\" : {\n" +
+                "          \"type\" : \"array\",\n" +
+                "          \"items\" : {\n" +
+                "            \"anyOf\" : [ {\n" +
+                "              \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.ETKeyNav\"\n" +
+                "            }, {\n" +
+                "              \"type\" : null\n" +
+                "            } ]\n" +
+                "          },\n" +
+                "          \"relationship\" : {\n" +
+                "            \"referentialConstraints\" : { }\n" +
+                "          }\n" +
+                "        }\n" +
+                "      }\n" +
+                "    }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"olingo.odata.test1.ETMedia\" : {\n" +
+                "      \"type\" : \"object\",\n" +
+                "      \"hasStream\" : true,\n" +
+                "      \"keys\" : [ {\n" +
+                "        \"name\" : \"PropertyInt16\"\n" +
+                "      } ],\n" +
+                "      \"properties\" : {\n" +
+                "        \"PropertyInt16\" : {\n" +
+                "          \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/Edm.Int16\"\n" +
+                "        }\n" +
+                "      }\n" +
+                "    }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"PropertyDecimal\" : {\n" +
+                "          \"anyOf\" : [ {\n" +
+                "            \"type\" : \"number\",\n" +
+                "            \"multipleOf\" : 1.0E-5,\n" +
+                "            \"minimum\" : -999999.99999,\n" +
+                "            \"maximum\" : 999999.99999\n" +
+                "          }, {\n" +
+                "            \"type\" : null\n" +
+                "          } ]\n" +
+                "        }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"CollPropertyDateTimeOffset\" : {\n" +
+                "          \"type\" : \"array\",\n" +
+                "          \"items\" : {\n" +
+                "            \"anyOf\" : [ {\n" +
+                "              \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/Edm.DateTimeOffset\"\n" +
+                "            }, {\n" +
+                "              \"pattern\" : \"^[^.]*$\"\n" +
+                "            } ]\n" +
+                "          }\n" +
+                "        }";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"entityContainer\" : {\n" +
+                "        \"name\" : \"Container\",";
+        assertThat(metadata, containsString(expectedString));
+
+        expectedString=
+        "\"olingo.odata.test1.ETTwoBase\" : {\n" +
+                "      \"type\" : \"object\",\n" +
+                "      \"allOf\" : [ {\n" +
+                "        \"$ref\" : \"http://docs.oasis-open.org/odata/odata-json-csdl/v4.0/edm.json#/" +
+                "definitions/olingo.odata.test1.ETBase\"\n" +
+                "      } ],\n" +
+                "      \"properties\" : {\n" +
+                "        \"AdditionalPropertyString_6\" : {\n" +
+                "          \"type\" : [ \"string\", null ]\n" +
+                "        }\n" +
+                "      }\n" +
+                "    }";
+        assertThat(metadata, containsString(expectedString));
+
+    }
+
+
+    private List<EdmxReference> getEdmxReferences() {
+        EdmxReference reference = new EdmxReference(URI.create(CORE_VOCABULARY));
+        reference.addInclude(new EdmxReferenceInclude("Org.OData.Core.V1", "Core"));
+        return Arrays.asList(reference);
+    }
+}