[OLINGO-324] merge metadata and payload
diff --git a/datajs/demo/tester.html b/datajs/demo/tester.html
index 43bca29..0b0caa0 100644
--- a/datajs/demo/tester.html
+++ b/datajs/demo/tester.html
@@ -42,12 +42,13 @@
         <button id="btnJSONwithMetaData">JSON with MetaData</button><br/>
         <div id='resultsArea' data-type="json">
         </div>
-        <script type='text/html' id='template'>
-            {{#items}}
-            <p><a href="{{id}}">{{name}}</a></p>
-            {{/items}}
-        </script>
         <script>
+            //var x = eval("(function (w, undefined) {alert('A '+JSON.stringify(w.screen));})(this);");
+            //(function () {
+            //    var x = eval("(function (w, undefined) {alert('B '+JSON.stringify(w.screen));})(this);");
+            //})();
+            
+
             function show(data) {
                 $('#resultsArea').empty();
                 var code = $('<code data-type="json"></code>').text(JSON.stringify(data))
@@ -78,34 +79,34 @@
                     requestUri: "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata", //"http://localhost:6630/PrimitiveKeys.svc/$metadata",
                     data: null,
                 };
-                OData.read(metadataRequest, metaDatasuccess, errorFunc,OData.metadataHandler);
+                datajs.V4.oData.read(metadataRequest, metaDatasuccess, errorFunc,datajs.V4.oData.metadataHandler);
             };
 
             $('#startXML').on("click", function(){
                 //var requestUri = 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods';
                 var requestUri ='http://localhost:4003/sap/bc/ds/odata/v4/ESMixPrimCollComp?$format=xml';
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
             $('#btnJSON_none').on("click", function(){
                 var requestUri = {
                     requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
                     headers : { Accept : 'application/json;odata.metadata=none' }
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
             $('#btnJSON_minimal').on("click", function(){
                 var requestUri = {
                     requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
                     headers : { Accept : 'application/json;odata.metadata=minimal' }
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
             $('#btnJSON_full').on("click", function(){
                 var requestUri = {
                     requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
                     headers : { Accept : 'application/json;odata.metadata=full' }
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
 
             $('#btnJSON_full_to_all').on("click", function(){
@@ -115,7 +116,7 @@
                     extendMetadataToLevel : 'all' ,
                     recognizeDates : false
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
             $('#btnJSON_full_to_all_date_conversion').on("click", function(){
                 var requestUri = {
@@ -124,7 +125,7 @@
                     extendMetadataToLevel : 'all' ,
                     recognizeDates : true
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
             $('#btnJSON_full_date_conversion').on("click", function(){
                 var requestUri = {
@@ -132,7 +133,7 @@
                     headers : { Accept : 'application/json;odata.metadata=full' },
                     recognizeDates : true
                 };
-                OData.read(requestUri, success, errorFunc);
+                datajs.V4.oData.read(requestUri, success, errorFunc);
             });
 
             $('#btnMetaData').on("click", function(){
@@ -150,7 +151,7 @@
                     data: null,
                 };
 
-                OData.read(metadataRequest, success, errorFunc,OData.metadataHandler);
+                datajs.V4.oData.read(metadataRequest, success, errorFunc,datajs.V4.oData.metadataHandler);
             });
 
 
@@ -163,7 +164,7 @@
                         extendMetadataToLevel : 'all' ,
                         recognizeDates : false
                     };
-                    OData.read(requestUri, success, errorFunc, null, null, metadata);
+                    datajs.V4.oData.read(requestUri, success, errorFunc, null, null, metadata);
                 }
                 getMetaData(metaDatasuccess);
             });
@@ -176,7 +177,7 @@
                         extendMetadataToLevel : 'full' ,
                         recognizeDates : false
                     };
-                    OData.read(requestUri, success, errorFunc, null, null, metadata);
+                    datajs.V4.oData.read(requestUri, success, errorFunc, null, null, metadata);
                 }
                 getMetaData(metaDatasuccess);
             });
@@ -198,11 +199,11 @@
 
                 var metaDatasuccess = function(metadata){
                     var requestUri = 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods';
-                    OData.read(requestUri, success, errorFunc, null, null, metadata);
+                    datajs.V4.oData.read(requestUri, success, errorFunc, null, null, metadata);
                 }
 
 
-                OData.read(metadataRequest, metaDatasuccess, errorFunc,OData.metadataHandler);
+                datajs.V4.oData.read(metadataRequest, metaDatasuccess, errorFunc,datajs.V4.oData.metadataHandler);
             });
 
         </script>
diff --git a/datajs/demo/testerV2.html b/datajs/demo/testerV2.html
index a480f8f..b9bf1c8 100644
--- a/datajs/demo/testerV2.html
+++ b/datajs/demo/testerV2.html
@@ -28,20 +28,17 @@
         </style>
     </head>   
     <body>
-        <button id="startXML">startXML</button><br/>
-        <button id="startJSON">startJSON</button><br/>
+        <button id="btnMetaData">MetaData</button><br/>
+        <button id="btnJSON_minimal">pure JSON</button><br/>
+
         <div id='resultsArea'>
 
         </div>
-        <script type='text/html' id='template'>
-            {{#items}}
-            <p><a href="{{id}}">{{name}}</a></p>
-            {{/items}}
-        </script>
         <script>
             function show(data) {
                 $('#resultsArea').empty();
-                $('#resultsArea').text(JSON.stringify(data))
+                var code = $('<code data-type="json"></code>').text(JSON.stringify(data))
+                $('#resultsArea').append(code);
                 $('code[data-type]').prettify();
             }
             function success(data) {
@@ -53,13 +50,19 @@
                 $("#resultsArea").text(JSON.stringify(err));
             }
 
+
+            $('#btnMetaData').on("click", function(){
+                var metadata;
+                OData.read("http://localhost:4003/sap/bc/ds/odata/v2/$metadata",success, errorFunc, OData.metadataHandler);
+            });
+
             $('#startXML').on("click", function(){
                 //var requestUri = 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods';
                 var requestUri ='http://localhost:4003/sap/bc/odata/Employees';
                 OData.read(requestUri, success, errorFunc);
             });
-            $('#startJSON').on("click", function(){
-                //var requestUri = 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods';
+            
+            $('#btnJSON_minimal').on("click", function(){
                 var requestUri ='http://localhost:4003/sap/bc/odata/Employees?$format=json';
                 OData.read(requestUri, success, errorFunc);
             });
diff --git a/datajs/src/index.js b/datajs/src/index.js
index c89a2b6..82fc374 100644
--- a/datajs/src/index.js
+++ b/datajs/src/index.js
@@ -17,11 +17,15 @@
  * under the License.
  */
 
-window.datajs = require('./lib/datajs.js');
-window.OData = require('./lib/odata.js');
+if ( window.datajs===undefined) {
+    window.datajs = {};
+}
 
-window.datajs.store = require('./lib/store.js');
-window.datajs.cache = require('./lib/cache.js');
+window.datajs.V4 = require('./lib/datajs.js');
+window.datajs.V4.oData = require('./lib/odata.js');
+
+window.datajs.V4.store = require('./lib/store.js');
+window.datajs.V4.cache = require('./lib/cache.js');
 
 function extend(target) {
     var sources = [].slice.call(arguments, 1);
diff --git a/datajs/src/lib/odata.js b/datajs/src/lib/odata.js
index 297a339..55f4a4e 100644
--- a/datajs/src/lib/odata.js
+++ b/datajs/src/lib/odata.js
@@ -18,19 +18,17 @@
 // odata.js
 
 // Imports
-exports.utils     = odataUtils =     require('./odata/utils.js');
-exports.handler   = odataHandler =   require('./odata/handler.js');
-exports.metadata  = odataMetadata =  require('./odata/metadata.js');
-exports.net       = odataNet      =  require('./odata/net.js');
-//exports.net       = odataNet      =  require('./odata/net-nodejs.js');//testing only
-exports.gml       =                  require('./odata/gml.js');
-exports.jsonLight =                  require('./odata/json-light.js');
-exports.json      = odataJson =      require('./odata/json.js');
-exports.atom      = odataAtom =      require('./odata/atom.js');
-exports.xml       = odataXml =       require('./odata/xml.js');
-exports.batch     =                  require('./odata/batch.js');
-
-exports.metadataHandler =            odataMetadata.metadataHandler;
+var odataUtils    = exports.utils     = require('./odata/utils.js');
+var odataHandler  = exports.handler   = require('./odata/handler.js');
+var odataMetadata = exports.metadata  = require('./odata/metadata.js');
+var odataNet      = exports.net       = require('./odata/net.js');
+                    exports.gml       = require('./odata/gml.js');
+var odataJson     = exports.json      = require('./odata/json.js');
+var odataAtom     = exports.atom      = require('./odata/atom.js');
+var odataXml      = exports.xml       = require('./odata/xml.js');
+                    exports.batch     = require('./odata/batch.js');
+                    
+exports.metadataHandler =  odataMetadata.metadataHandler;
 
 
 
diff --git a/datajs/src/lib/odata/json-light.js b/datajs/src/lib/odata/json-light.js
index eddd58c..aefa27f 100644
--- a/datajs/src/lib/odata/json-light.js
+++ b/datajs/src/lib/odata/json-light.js
@@ -32,6 +32,7 @@
 var getURIInfo = utils.getURIInfo;
 var isArray = utils.isArray;
 var isDate = utils.isDate;
+var isObject = utils.isObject;
 var normalizeURI = utils.normalizeURI;
 var renameProperty = utils.renameProperty;
 var undefinedDefault = utils.undefinedDefault;
@@ -72,21 +73,15 @@
 var PAYLOADTYPE_FEED = "f";
 var PAYLOADTYPE_ENTRY = "e";
 var PAYLOADTYPE_PROPERTY = "p";
+var PAYLOADTYPE_COLLECTION = "c";
+var PAYLOADTYPE_ENUMERATION_PROPERTY = "enum";
+var PAYLOADTYPE_SVCDOC = "s";
 var PAYLOADTYPE_ENTITY_REF_LINK = "erl";
 var PAYLOADTYPE_ENTITY_REF_LINKS = "erls";
+
 var PAYLOADTYPE_VALUE = "v";
-var PAYLOADTYPE_BINARY_VALUE = "bv";
-var PAYLOADTYPE_COLLECTION = "c";
-var PAYLOADTYPE_SVCDOC = "s";
-var PAYLOADTYPE_METADOC = "m";
-var PAYLOADTYPE_ERROR = "err";
-var PAYLOADTYPE_BATCH = "b";
-var PAYLOADTYPE_PARAMETER = "para";
-var PAYLOADTYPE_IND_PROPERTY = "ip";
+
 var PAYLOADTYPE_DELTA = "d";
-var PAYLOADTYPE_ASYNC = "a";
-
-
 var DELTATYPE_FEED = "f";
 var DELTATYPE_DELETED_ENTRY = "de";
 var DELTATYPE_LINK = "l";
@@ -197,6 +192,7 @@
     return isComplex(data) && ((odataAnnotationPrefix + "id") in data);
 };
 
+/*
 var jsonLightIsNavigationProperty = function (name, data, dataItemModel) {
     /// <summary>Determines whether a data item in a JSON light object is a navigation property.</summary>
     /// <param name="name" type="String">Name of the data item to test.</param>
@@ -213,6 +209,7 @@
     var value = isArray(data[name]) ? data[name][0] : data[name];
     return jsonLightIsEntry(value);
 };
+*/
 
 var jsonLightIsPrimitiveType = function (typeName) {
     /// <summary>Determines whether a type name is a primitive type in a JSON light payload.</summary>
@@ -530,6 +527,103 @@
     return null;
 };
 
+var jsonLightReadComplexObjectNew = function (data, property, baseURI, model, demandedFormat, recognizeDates) {
+    var type = property.type;
+    if (isCollectionType(property.type)) {
+        type =property.type.substring(11,property.type.length-1);
+    }
+
+    data['@odata.type'] = '#'+type;
+
+
+
+    var propertyType = lookupComplexType(type, model);
+    if (propertyType === null)  {
+        return; //TODO check what to do if the type is not known e.g. type #GeometryCollection
+    }
+
+    var curType = propertyType;
+
+
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var propertyValue = data[name];
+            var property = lookupProperty(curType.property,name); //TODO SK add check for parent type
+
+            while (( property === null) && (curType.baseType !== undefined)) {
+                curType = lookupEntityType(curType.baseType, model);
+                property = lookupProperty(curType.property,name);
+            }
+            if (demandedFormat === 3)  {
+                if ( isArray(propertyValue)) {
+                    data[name+'@odata.type'] = '#' + property.type;
+                    for ( var i = 0; i < propertyValue.length; i++) {
+                        jsonLightReadComplexObjectNew(propertyValue[0], property,baseURI,model,demandedFormat, recognizeDates);
+                    }
+                } else if (isObject(propertyValue) && (propertyValue!= null)) {
+                    jsonLightReadComplexObjectNew(propertyValue, property,baseURI,model,demandedFormat, recognizeDates);
+                } else {
+                    data[name+'@odata.type'] = '#' + property.type;
+                }
+                
+            } else {
+
+            }
+        }
+    }
+}
+
+
+var jsonLightReadObjectNew = function (data, objectInfo, baseURI, model, demandedFormat, recognizeDates) {
+    //var obj = {};
+
+    data['@odata.type'] = '#'+objectInfo.typeName;
+
+    var keyType = objectInfo.type;
+    while (( keyType.key === undefined) && (keyType.baseType !== undefined)) {
+        keyType = lookupEntityType(keyType.baseType, model);
+    }
+
+    var lastIdSegment = objectInfo.name + jsonLightGetEntryKey(data, keyType);
+    data['@odata.id'] = baseURI.substring(0, baseURI.lastIndexOf("$metadata")) + lastIdSegment;
+    data['@odata.editLink'] = lastIdSegment;
+
+    var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
+    //jsonLightComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
+
+    
+
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var curType = objectInfo.type;
+            var propertyValue = data[name];
+            var property = lookupProperty(curType.property,name); //TODO SK add check for parent type
+
+            while (( property === null) && (curType.baseType !== undefined)) {
+                curType = lookupEntityType(curType.baseType, model);
+                property = lookupProperty(curType.property,name);
+            }
+            if (demandedFormat === 3)  {
+                if ( isArray(propertyValue)) {
+                    data[name+'@odata.type'] = '#' + property.type;
+                    for ( var i = 0; i < propertyValue.length; i++) {
+                        jsonLightReadComplexObjectNew(propertyValue[0], property,baseURI,model,demandedFormat, recognizeDates);
+                    }
+                } else if (isObject(propertyValue) && (propertyValue!= null)) {
+                    jsonLightReadComplexObjectNew(propertyValue, property,baseURI,model,demandedFormat, recognizeDates);
+                } else {
+                    data[name+'@odata.type'] = '#' + property.type;
+                }
+                
+            } else {
+
+            }
+        }
+    }
+
+    return data;
+};
+
 var jsonLightReadObject = function (data, objectInfo, baseURI, model, recognizeDates) {
     /// <summary>Converts a JSON light entry or complex type object into its library representation.</summary>
     /// <param name="data" type="Object">JSON light entry or complex type object to convert.</param>
@@ -673,6 +767,34 @@
     }
 };
 
+var jsonLightReadFeedNew = function (data, feedInfo, baseURI, model, demandedFormat,recognizeDates) {
+    var entries = [];
+    var items = data.value;
+    for (i = 0, len = items.length; i < len; i++) {
+        //TODO SK check if items[i] has @odata.type and use this type instead of  feedinfo
+        
+        if ( items[i]['@odata.type'] !== undefined) {
+            var typeName = items[i]['@odata.type'].substring(1);
+            var type = lookupEntityType( typeName, model);
+            var entryInfo = {
+                contentTypeOdata : feedInfo.contentTypeOdata,
+                detectedPayloadKind : feedInfo.detectedPayloadKind,
+                name : feedInfo.name,
+                type : type,
+                typeName : typeName
+            };
+
+            entry = jsonLightReadObjectNew(items[i], entryInfo, baseURI, model, demandedFormat,recognizeDates);
+        } else {
+            entry = jsonLightReadObjectNew(items[i], feedInfo, baseURI, model, demandedFormat,recognizeDates);
+        }
+        
+        entries.push(entry);
+    }
+    data.value = entries;
+    return data;
+};
+
 var jsonLightReadFeed = function (data, feedInfo, baseURI, model, recognizeDates) {
     /// <summary>Converts a JSON light feed or top level collection property object into its library representation.</summary>
     /// <param name="data" type="Object">JSON light feed object to convert.</param>
@@ -712,7 +834,7 @@
     /// <returns type="string">Entry instance key.</returns>
 
     var entityInstanceKey;
-    var entityKeys = entityModel.key.propertyRef;
+    var entityKeys = entityModel.key[0].propertyRef;
     var type;
     entityInstanceKey = "(";
     if (entityKeys.length == 1) {
@@ -1040,277 +1162,10 @@
     return { workspaces: [workspace] };
 };
 
-var jsonLightMakePayloadInfo = function (kind, type) {
-    /// <summary>Creates an object containing information for the json light payload.</summary>
-    /// <param name="kind" type="String">JSON light payload kind, one of the PAYLOADTYPE_XXX constant values.</param>
-    /// <param name="typeName" type="String">Type name of the JSON light payload.</param>
-    /// <returns type="Object">Object with kind and type fields.</returns>
-
-    /// <field name="kind" type="String">Kind of the JSON light payload. One of the PAYLOADTYPE_XXX constant values.</field>
-    /// <field name="type" type="String">Data type of the JSON light payload.</field>
-
-    return { kind: kind, type: type || null };
-};
-
-/// <summary>Creates an object containing information for the context</summary>
-/// ...
-/// <returns type="Object">Object with type information
-/// attribute detectedPayloadKind(optional): see constants starting with PAYLOADTYPE_
-/// attribute deltaKind(optional): deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
-/// attribute typeName(optional): name of the type
-/// attribute type(optional): object containing type information for entity- and complex-types ( null if a typeName is a primitive)
-///  </returns>
-var parseContextUriFragment = function( fragment, model ) {
-    var ret = {};
-
-    
-    if (fragment.indexOf('/') === -1 ) {
-        if (fragment.length === 0) {
-            // Capter 10.1
-            ret.detectedPayloadKind = PAYLOADTYPE_SVCDOC;
-            return ret;
-        } else if (fragment === 'Edm.Null') {
-            // Capter 10.15
-            ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
-            ret.isNullProperty = true;
-            return ret;
-        } else if (fragment === 'Collection($ref)') {
-            // Capter 10.11
-            ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINKS;
-            return ret;
-        } else if (fragment === '$ref') {
-            // Capter 10.12
-            ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINK;
-            return ret;
-        } else {
-            //TODO check for navigation resource
-        }
-    } 
-
-    ret.type = undefined;
-    ret.typeName = undefined;
-
-    var fragmentParts = fragment.split("/");
-    
-    for(var i = 0; i < fragmentParts.length; ++i) {
-        var fragment = fragmentParts[i];
-        if (ret.typeName === undefined) {
-            //preparation
-            if ( fragment.indexOf('(') !== -1 ) {
-                //remove the query function, cut fragment to matching '('
-                var index = fragment.length - 2 ;
-                for ( var rCount = 1; rCount > 0 && index > 0; --index) {
-                    if ( fragment.charAt(index)=='(') {
-                        rCount --;
-                    } else if ( fragment.charAt(index)==')') {
-                        rCount ++;    
-                    }
-                }
-
-                if (index === 0) {
-                    //TODO throw error
-                }
-
-                //remove the projected entity from the fragment; TODO decide if we want to store the projected entity 
-                var inPharenthesis = fragment.substring(index+2,fragment.length - 1);
-                fragment = fragment.substring(0,index+1);
-
-                if (utils.startsWith(fragment, 'Collection')) {
-                    ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
-                    // Capter 10.14
-                    ret.typeName = inPharenthesis;
-
-                    var type = lookupEntityType(ret.typeName, model);
-                    if ( type !== null) {
-                        ret.type = type;
-                        continue;
-                    }
-                    type = lookupComplexType(ret.typeName, model);
-                    if ( type !== null) {
-                        ret.type = type;
-                        continue;
-                    }
-
-                    ret.type = null;//in case of #Collection(Edm.String) only lastTypeName is filled
-                    continue;
-                } else {
-                    // projection: Capter 10.7, 10.8 and 10.9
-                    ret.projection = inPharenthesis;
-                }
-            }
-
-            var container = lookupDefaultEntityContainer(model);
-
-            //check for entity
-            var entitySet = lookupEntitySet(container.entitySet, fragment);
-            if ( entitySet !== null) {
-                ret.typeName = entitySet.entityType;
-                ret.type = lookupEntityType( ret.typeName, model);
-                ret.detectedPayloadKind = PAYLOADTYPE_FEED;
-                // Capter 10.2
-                continue;
-            }
-
-            //check for singleton
-            var singleton = lookupSingleton(container.singleton, fragment);
-            if ( singleton !== null) {
-                ret.typeName = singleton.entityType;
-                ret.type = lookupEntityType( ret.typeName, model);
-                ret.detectedPayloadKind =  PAYLOADTYPE_ENTRY;
-                // Capter 10.4
-                continue;
-            }
-
-            if (jsonLightIsPrimitiveType(fragment)) {
-                ret.typeName = fragment;
-                ret.type = null;
-                ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
-                continue;
-            }
-
-            //TODO throw ERROR
-        } else {
-            //check for $entity
-            if (utils.endsWith(fragment, '$entity') && (ret.detectedPayloadKind === PAYLOADTYPE_FEED)) {
-                ret.detectedPayloadKind = PAYLOADTYPE_ENTRY;
-                // Capter 10.3 and 10.6
-                continue;
-            } 
-
-            //check for derived types
-            if (fragment.indexOf('.') !== -1) {
-                // Capter 10.6
-                ret.typeName = fragment;
-                var type = lookupEntityType(ret.typeName, model);
-                if ( type !== null) {
-                    ret.type = type;
-                    continue;
-                }
-                type = lookupComplexType(ret.typeName, model);
-                if ( type !== null) {
-                    ret.type = type;
-                    continue;
-                }
-
-                //TODO throw ERROR invalid type
-            }
-
-            //check for property value
-            if ( ret.detectedPayloadKind === PAYLOADTYPE_FEED || ret.detectedPayloadKind === PAYLOADTYPE_ENTRY) {
-                var property = lookupProperty(ret.type.property, fragment);
-                if (property !== null) {
-                    ret.typeName = property.type;
-                    ret.type = lookupComplexType(ret.typeName, model);
-                    ret.detectedPayloadKind = PAYLOADTYPE_PROPERTY;
-                    // Capter 10.15
-                }
-                continue;
-            }
-
-            if (fragment === '$delta') {
-                ret.deltaKind = DELTATYPE_FEED;
-                continue;
-            } else if (utils.endsWith(fragment, '/$deletedEntity')) {
-                ret.deltaKind = DELTATYPE_DELETED_ENTRY;
-                continue;
-            } else if (utils.endsWith(fragment, '/$link')) {
-                ret.deltaKind = DELTATYPE_LINK;
-                continue;
-            } else if (utils.endsWith(fragment, '/$deletedLink')) {
-                ret.deltaKind = DELTATYPE_DELETED_LINK;
-                continue;
-            }
-            //TODO throw ERROr
-        }
-    }
-    return ret;
-};
-
-var jsonLightPayloadInfo = function (data, model) {
-    /// <summary>Infers the information describing the JSON light payload from its metadata annotation, structure, and data model.</summary>
-    /// <param name="data" type="Object">Json light response payload object.</param>
-    /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-    /// <remarks>
-    ///     If the arguments passed to the function don't convey enough information about the payload to determine without doubt that the payload is a feed then it
-    ///     will try to use the payload object structure instead.  If the payload looks like a feed (has value property that is an array or non-primitive values) then
-    ///     the function will report its kind as PAYLOADTYPE_FEED unless the inferFeedAsComplexType flag is set to true. This flag comes from the user request
-    ///     and allows the user to control how the library behaves with an ambigous JSON light payload.
-    /// </remarks>
-    /// <returns type="Object">
-    ///     Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
-    /// </returns>
-
-    var metadataUri = data[contextUrlAnnotation];
-    if (!metadataUri || typeof metadataUri !== "string") {
-        return null;
-    }
-
-    var fragmentStart = metadataUri.lastIndexOf("#");
-    if (fragmentStart === -1) {
-        return jsonLightMakePayloadInfo(PAYLOADTYPE_SVCDOC);
-    }
-
-    var elementStart = metadataUri.indexOf("@Element", fragmentStart);
-    var fragmentEnd = elementStart - 1;
-
-    if (fragmentEnd < 0) {
-        fragmentEnd = metadataUri.indexOf("?", fragmentStart);
-        if (fragmentEnd === -1) {
-            fragmentEnd = metadataUri.length;
-        }
-    }
-
-    var fragment = metadataUri.substring(fragmentStart + 1, fragmentEnd);
-    if (fragment.indexOf("/$links/") > 0) {
-        return jsonLightMakePayloadInfo(PAYLOADTYPE_LINKS);
-    }
-
-    var ret = parseContextUriFragment(fragment,model);
-
-    return ret;
 
 
-};
 
-var jsonLightReadPayload = function (data, model, recognizeDates, inferFeedAsComplexType, contentTypeOdata) {
-    /// <summary>Converts a JSON light response payload object into its library's internal representation.</summary>
-    /// <param name="data" type="Object">Json light response payload object.</param>
-    /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
-    /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
-    /// <param name="inferFeedAsComplexType" type="Boolean">True if a JSON light payload that looks like a feed should be reported as a complex type property instead.</param>
-    /// <param name="contentTypeOdata" type="string">Includes the type of json ( minimalmetadata, fullmetadata .. etc )</param>
-    /// <returns type="Object">Object in the library's representation.</returns>
 
-    if (!isComplex(data)) {
-        return data;
-    }
-
-    contentTypeOdata = contentTypeOdata || "minimal";
-    var baseURI = data[contextUrlAnnotation];
-    var payloadInfo = jsonLightPayloadInfo(data, model, inferFeedAsComplexType);
-    if (assigned(payloadInfo)) {
-        payloadInfo.contentTypeOdata = contentTypeOdata;
-    }
-    var typeName = null;
-    if (payloadInfo) {
-        delete data[contextUrlAnnotation];
-
-        typeName = payloadInfo.type;
-        switch (payloadInfo.kind) {
-            case PAYLOADTYPE_FEED:
-                return jsonLightReadFeed(data, payloadInfo, baseURI, model, recognizeDates);
-            case PAYLOADTYPE_COLLECTION:
-                return jsonLightReadTopCollectionProperty(data, typeName, baseURI, model, recognizeDates);
-            case PAYLOADTYPE_PRIMITIVE:
-                return jsonLightReadTopPrimitiveProperty(data, typeName, baseURI, recognizeDates);
-            case PAYLOADTYPE_SVCDOC:
-                return jsonLightReadSvcDocument(data, baseURI);
-            case PAYLOADTYPE_LINKS:
-                return jsonLightReadLinksDocument(data, baseURI);
-        }
-    }
-    return jsonLightReadObject(data, payloadInfo, baseURI, model, recognizeDates);
-};
 
 var jsonLightSerializableMetadata = ["@odata.type", "@odata.etag", "@odata.mediaEditLink", "@odata.mediaReadLink", "@odata.mediaContentType", "@odata.mediaEtag"];
 
@@ -1583,8 +1438,8 @@
 };
 
 // DATAJS INTERNAL START
-exports.jsonLightPayloadInfo = jsonLightPayloadInfo;
-exports.jsonLightReadPayload = jsonLightReadPayload;
+//exports.jsonLightPayloadInfo = jsonLightPayloadInfo;
+//exports.jsonLightReadPayload = jsonLightReadPayload;
 exports.formatJsonLight = formatJsonLight;
 exports.formatJsonLightRequestPayload = formatJsonLightRequestPayload;
 // DATAJS INTERNAL END
diff --git a/datajs/src/lib/odata/json.js b/datajs/src/lib/odata/json.js
index f5293bf..087f4cf 100644
--- a/datajs/src/lib/odata/json.js
+++ b/datajs/src/lib/odata/json.js
@@ -25,18 +25,21 @@
 var utils    = require('./../datajs.js').utils;
 var oDataUtils    = require('./utils.js');
 var oDataHandler    = require('./handler.js');
-var oJsonLight    = require('./json-light.js');
 
+var odataNs = "odata";
+var odataAnnotationPrefix = odataNs + ".";
+var contextUrlAnnotation = "@" + odataAnnotationPrefix + "context";
 
+var assigned = utils.assigned;
 var defined = utils.defined;
 var extend = utils.extend;
 var isArray = utils.isArray;
 var isDate = utils.isDate;
+var isObject = utils.isObject;
 var normalizeURI = utils.normalizeURI;
 var parseInt10 = utils.parseInt10;
 
 var contentType = oDataUtils.contentType;
-var jsonLightReadPayload = oJsonLight.jsonLightReadPayload;
 var formatDateTimeOffset = oDataUtils.formatDateTimeOffset;
 var formatDuration = oDataUtils.formatDuration;
 var formatJsonLight = oDataUtils.formatJsonLight;
@@ -44,9 +47,13 @@
 var getCanonicalTimezone = oDataUtils.getCanonicalTimezone;
 var handler = oDataUtils.handler;
 var isComplex = oDataUtils.isComplex;
+var isCollectionType = oDataUtils.isCollectionType;
 var lookupComplexType = oDataUtils.lookupComplexType;
 var lookupEntityType = oDataUtils.lookupEntityType;
 var lookupSingleton = oDataUtils.lookupSingleton;
+var lookupEntitySet = oDataUtils.lookupEntitySet;
+var lookupDefaultEntityContainer = oDataUtils.lookupDefaultEntityContainer;
+var lookupProperty = oDataUtils.lookupProperty;
 var MAX_DATA_SERVICE_VERSION = oDataUtils.MAX_DATA_SERVICE_VERSION;
 var maxVersion = oDataUtils.maxVersion;
 var parseDateTime = oDataUtils.parseDateTime;
@@ -54,13 +61,29 @@
 var parseTimezone = oDataUtils.parseTimezone;
 var payloadTypeOf = oDataUtils.payloadTypeOf;
 var traverse = oDataUtils.traverse;
-var formatJsonLightRequestPayload = oJsonLight.formatJsonLightRequestPayload;
 
 // CONTENT START
 
+var PAYLOADTYPE_FEED = "f";
+var PAYLOADTYPE_ENTRY = "e";
+var PAYLOADTYPE_PROPERTY = "p";
+var PAYLOADTYPE_COLLECTION = "c";
+var PAYLOADTYPE_ENUMERATION_PROPERTY = "enum";
+var PAYLOADTYPE_SVCDOC = "s";
+var PAYLOADTYPE_ENTITY_REF_LINK = "erl";
+var PAYLOADTYPE_ENTITY_REF_LINKS = "erls";
+
+var PAYLOADTYPE_VALUE = "v";
+
+var PAYLOADTYPE_DELTA = "d";
+var DELTATYPE_FEED = "f";
+var DELTATYPE_DELETED_ENTRY = "de";
+var DELTATYPE_LINK = "l";
+var DELTATYPE_DELETED_LINK = "dl";
+
 var jsonMediaType = "application/json";
 var jsonContentType = oDataHandler.contentType(jsonMediaType);
-
+/*
 var jsonReadAdvertisedActionsOrFunctions = function (value) {
     /// <summary>Reads and object containing action or function metadata and maps them into a single array of objects.</summary>
     /// <param name="value" type="Object">Object containing action or function metadata.</param>
@@ -74,8 +97,9 @@
         }
     }
     return result;
-};
+};*/
 
+/*
 var jsonApplyMetadata = function (value, metadata, dateParser, recognizeDates) {
     /// <summary>Applies metadata coming from both the payload and the metadata object to the value.</summary>
     /// <param name="value" type="Object">Data on which the metada is going to be applied.</param>
@@ -136,8 +160,8 @@
         }
     }
     return value;
-};
-
+};*/
+/*
 var isJsonLight = function (contentType) {
     /// <summary>Tests where the content type indicates a json light payload.</summary>
     /// <param name="contentType">Object with media type and properties dictionary.</param>
@@ -148,8 +172,8 @@
         return odata === "none" || odata === "minimal" || odata === "full";
     }
     return false;
-};
-
+};*/
+/*
 var normalizeServiceDocument = function (data, baseURI) {
     /// <summary>Normalizes a JSON service document to look like an ATOM service document.</summary>
     /// <param name="data" type="Object">Object representation of service documents as deserialized.</param>
@@ -169,7 +193,7 @@
     }
 
     return { workspaces: [workspace] };
-};
+};*/
 
 // The regular expression corresponds to something like this:
 // /Date(123+60)/
@@ -268,8 +292,6 @@
     }
     demandedFormat = (demandedFormat === undefined) ? 1 : demandedFormat;
 
-    //return jsonLightReadPayload(json, model, recognizeDates, inferJsonLightFeedAsObject, context.contentType.properties['odata.metadata']);
-
     if ( payloadFormat >= demandedFormat) {
         //there is no need to add additional metadata
         if (recognizeDates) {
@@ -294,7 +316,7 @@
             if (!utils.isArray(model)) { // array was default for model in datajsV3 3.0 
                 //TODO use metadata in context to determine which properties need to be converted
                 // and extend the metadata
-                return extendMetadataFromContext(json,context,model,recognizeDates);
+                return extendMetadataFromContext(json,context,model,demandedFormat, recognizeDates);
             } else {
                 //error metadata in context required, TODO: throw a to be defined exception
             }
@@ -303,19 +325,12 @@
             return json;
         }
     }
-
-    
 };
 
-var extendMetadataFromContext = function(json,context, model,recognizeDates) {
-    return jsonLightReadPayload(json, model, recognizeDates, false, context.contentType.properties['odata.metadata']);
+var extendMetadataFromContext = function(json,context, model,demandedFormat,recognizeDates) {
+    return jsonLightReadPayload(json, model, demandedFormat,recognizeDates, false, context.contentType.properties['odata.metadata']);
 };
 
-var convertPrimitivetypesGeneric = function(data) {
-    
-};
-
-
 var convertPrimitivetypesOnMetadataFull = function(data) {
     /// <summary>Converts some primitive data types in payload</summary>
     /// <param name="data">Date which will be extendet</param>
@@ -419,7 +434,7 @@
 
 
 
-
+/*
 var jsonToString = function (data) {
     /// <summary>Converts the data into a JSON string.</summary>
     /// <param name="data">Data to serialize.</param>
@@ -440,7 +455,7 @@
         Date.prototype.toJSON = dateToJSON;
     }
     return result;
-};
+};*/
 
 var jsonSerializer = function (handler, data, context) {
     /// <summary>Serializes the data by returning its string representation.</summary>
@@ -463,6 +478,34 @@
     return undefined;
 };
 
+var formatJsonLightRequestPayload = function (data) {
+    if (!data) {
+        return data;
+    }
+
+    if (isPrimitive(data)) {
+        return data;
+    }
+
+    if (isArray(data)) {
+        var newArrayData = [];
+        var i, len;
+        for (i = 0, len = data.length; i < len; i++) {
+            newArrayData[i] = formatJsonLightRequestPayload(data[i]);
+        }
+
+        return newArrayData;
+    }
+
+    var newdata = {};
+    for (var property in data) {
+        if (isJsonLightSerializableProperty(property)) {
+            newdata[property] = formatJsonLightRequestPayload(data[property]);
+        }
+    }
+
+    return newdata;
+};
 var jsonReplacer = function (_, value) {
     /// <summary>JSON replacer function for converting a value to its JSON representation.</summary>
     /// <param value type="Object">Value to convert.</param>
@@ -479,6 +522,385 @@
     }
 };
 
+
+var jsonLightMakePayloadInfo = function (kind, type) {
+    /// <summary>Creates an object containing information for the json light payload.</summary>
+    /// <param name="kind" type="String">JSON light payload kind, one of the PAYLOADTYPE_XXX constant values.</param>
+    /// <param name="typeName" type="String">Type name of the JSON light payload.</param>
+    /// <returns type="Object">Object with kind and type fields.</returns>
+
+    /// <field name="kind" type="String">Kind of the JSON light payload. One of the PAYLOADTYPE_XXX constant values.</field>
+    /// <field name="type" type="String">Data type of the JSON light payload.</field>
+
+    return { kind: kind, type: type || null };
+};
+
+/// <summary>Creates an object containing information for the context</summary>
+/// ...
+/// <returns type="Object">Object with type information
+/// attribute detectedPayloadKind(optional): see constants starting with PAYLOADTYPE_
+/// attribute deltaKind(optional): deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
+/// attribute typeName(optional): name of the type
+/// attribute type(optional): object containing type information for entity- and complex-types ( null if a typeName is a primitive)
+///  </returns>
+var parseContextUriFragment = function( fragments, model ) {
+    var ret = {};
+
+    
+    if (fragments.indexOf('/') === -1 ) {
+        if (fragments.length === 0) {
+            // Capter 10.1
+            ret.detectedPayloadKind = PAYLOADTYPE_SVCDOC;
+            return ret;
+        } else if (fragments === 'Edm.Null') {
+            // Capter 10.15
+            ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
+            ret.isNullProperty = true;
+            return ret;
+        } else if (fragments === 'Collection($ref)') {
+            // Capter 10.11
+            ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINKS;
+            return ret;
+        } else if (fragments === '$ref') {
+            // Capter 10.12
+            ret.detectedPayloadKind = PAYLOADTYPE_ENTITY_REF_LINK;
+            return ret;
+        } else {
+            //TODO check for navigation resource
+        }
+    } 
+
+    ret.type = undefined;
+    ret.typeName = undefined;
+
+    var fragmentParts = fragments.split("/");
+    
+    for(var i = 0; i < fragmentParts.length; ++i) {
+        var fragment = fragmentParts[i];
+        if (ret.typeName === undefined) {
+            //preparation
+            if ( fragment.indexOf('(') !== -1 ) {
+                //remove the query function, cut fragment to matching '('
+                var index = fragment.length - 2 ;
+                for ( var rCount = 1; rCount > 0 && index > 0; --index) {
+                    if ( fragment.charAt(index)=='(') {
+                        rCount --;
+                    } else if ( fragment.charAt(index)==')') {
+                        rCount ++;    
+                    }
+                }
+
+                if (index === 0) {
+                    //TODO throw error
+                }
+
+                //remove the projected entity from the fragment; TODO decide if we want to store the projected entity 
+                var inPharenthesis = fragment.substring(index+2,fragment.length - 1);
+                fragment = fragment.substring(0,index+1);
+
+                if (utils.startsWith(fragment, 'Collection')) {
+                    ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
+                    // Capter 10.14
+                    ret.typeName = inPharenthesis;
+
+                    var type = lookupEntityType(ret.typeName, model);
+                    if ( type !== null) {
+                        ret.type = type;
+                        continue;
+                    }
+                    type = lookupComplexType(ret.typeName, model);
+                    if ( type !== null) {
+                        ret.type = type;
+                        continue;
+                    }
+
+                    ret.type = null;//in case of #Collection(Edm.String) only lastTypeName is filled
+                    continue;
+                } else {
+                    // projection: Capter 10.7, 10.8 and 10.9
+                    ret.projection = inPharenthesis;
+                }
+            }
+
+            var container = lookupDefaultEntityContainer(model);
+
+            //check for entity
+            var entitySet = lookupEntitySet(container.entitySet, fragment);
+            if ( entitySet !== null) {
+                ret.typeName = entitySet.entityType;
+                ret.type = lookupEntityType( ret.typeName, model);
+                ret.name = fragment;
+                ret.detectedPayloadKind = PAYLOADTYPE_FEED;
+                // Capter 10.2
+                continue;
+            }
+
+            //check for singleton
+            var singleton = lookupSingleton(container.singleton, fragment);
+            if ( singleton !== null) {
+                ret.typeName = singleton.entityType;
+                ret.type = lookupEntityType( ret.typeName, model);
+                ret.name = fragment;
+                ret.detectedPayloadKind =  PAYLOADTYPE_ENTRY;
+                // Capter 10.4
+                continue;
+            }
+
+            if (jsonLightIsPrimitiveType(fragment)) {
+                ret.typeName = fragment;
+                ret.type = null;
+                ret.detectedPayloadKind = PAYLOADTYPE_VALUE;
+                continue;
+            }
+
+            //TODO throw ERROR
+        } else {
+            //check for $entity
+            if (utils.endsWith(fragment, '$entity') && (ret.detectedPayloadKind === PAYLOADTYPE_FEED)) {
+                //TODO ret.name = fragment;
+                ret.detectedPayloadKind = PAYLOADTYPE_ENTRY;
+                // Capter 10.3 and 10.6
+                continue;
+            } 
+
+            //check for derived types
+            if (fragment.indexOf('.') !== -1) {
+                // Capter 10.6
+                ret.typeName = fragment;
+                var type = lookupEntityType(ret.typeName, model);
+                if ( type !== null) {
+                    ret.type = type;
+                    continue;
+                }
+                type = lookupComplexType(ret.typeName, model);
+                if ( type !== null) {
+                    ret.type = type;
+                    continue;
+                }
+
+                //TODO throw ERROR invalid type
+            }
+
+            //check for property value
+            if ( ret.detectedPayloadKind === PAYLOADTYPE_FEED || ret.detectedPayloadKind === PAYLOADTYPE_ENTRY) {
+                var property = lookupProperty(ret.type.property, fragment);
+                if (property !== null) {
+                    ret.typeName = property.type;
+                    ret.type = lookupComplexType(ret.typeName, model);
+                    ret.name = fragment;
+                    ret.detectedPayloadKind = PAYLOADTYPE_PROPERTY;
+                    // Capter 10.15
+                }
+                continue;
+            }
+
+            if (fragment === '$delta') {
+                ret.deltaKind = DELTATYPE_FEED;
+                continue;
+            } else if (utils.endsWith(fragment, '/$deletedEntity')) {
+                ret.deltaKind = DELTATYPE_DELETED_ENTRY;
+                continue;
+            } else if (utils.endsWith(fragment, '/$link')) {
+                ret.deltaKind = DELTATYPE_LINK;
+                continue;
+            } else if (utils.endsWith(fragment, '/$deletedLink')) {
+                ret.deltaKind = DELTATYPE_DELETED_LINK;
+                continue;
+            }
+            //TODO throw ERROr
+        }
+    }
+    return ret;
+};
+
+var jsonLightPayloadInfo = function (data, model) {
+    /// <summary>Infers the information describing the JSON light payload from its metadata annotation, structure, and data model.</summary>
+    /// <param name="data" type="Object">Json light response payload object.</param>
+    /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
+    /// <remarks>
+    ///     If the arguments passed to the function don't convey enough information about the payload to determine without doubt that the payload is a feed then it
+    ///     will try to use the payload object structure instead.  If the payload looks like a feed (has value property that is an array or non-primitive values) then
+    ///     the function will report its kind as PAYLOADTYPE_FEED unless the inferFeedAsComplexType flag is set to true. This flag comes from the user request
+    ///     and allows the user to control how the library behaves with an ambigous JSON light payload.
+    /// </remarks>
+    /// <returns type="Object">
+    ///     Object with kind and type fields. Null if there is no metadata annotation or the payload info cannot be obtained..
+    /// </returns>
+
+    var metadataUri = data[contextUrlAnnotation];
+    if (!metadataUri || typeof metadataUri !== "string") {
+        return null;
+    }
+
+    var fragmentStart = metadataUri.lastIndexOf("#");
+    if (fragmentStart === -1) {
+        return jsonLightMakePayloadInfo(PAYLOADTYPE_SVCDOC);
+    }
+
+    var fragment = metadataUri.substring(fragmentStart + 1);
+    return parseContextUriFragment(fragment,model);
+};
+
+var jsonLightReadPayload = function (data, model, demandedFormat,recognizeDates, inferFeedAsComplexType, contentTypeOdata) {
+    /// <summary>Converts a JSON light response payload object into its library's internal representation.</summary>
+    /// <param name="data" type="Object">Json light response payload object.</param>
+    /// <param name="model" type="Object">Object describing an OData conceptual schema.</param>
+    /// <param name="recognizeDates" type="Boolean" optional="true">Flag indicating whether datetime literal strings should be converted to JavaScript Date objects.</param>
+    /// <param name="inferFeedAsComplexType" type="Boolean">True if a JSON light payload that looks like a feed should be reported as a complex type property instead.</param>
+    /// <param name="contentTypeOdata" type="string">Includes the type of json ( minimalmetadata, fullmetadata .. etc )</param>
+    /// <returns type="Object">Object in the library's representation.</returns>
+
+    if (!isComplex(data)) {
+        return data;
+    }
+
+    contentTypeOdata = contentTypeOdata || "minimal";
+    var baseURI = data[contextUrlAnnotation];
+    var payloadInfo = jsonLightPayloadInfo(data, model, inferFeedAsComplexType);
+    if (assigned(payloadInfo)) {
+        payloadInfo.contentTypeOdata = contentTypeOdata;
+    }
+    var typeName = null;
+    if (payloadInfo) {
+        delete data[contextUrlAnnotation];
+
+        typeName = payloadInfo.type;
+        switch (payloadInfo.detectedPayloadKind) {
+            case PAYLOADTYPE_FEED:
+                return jsonLightReadFeedNew(data, payloadInfo, baseURI, model, demandedFormat,recognizeDates);
+            case PAYLOADTYPE_COLLECTION:
+                return jsonLightReadTopCollectionProperty(data, typeName, baseURI, model, recognizeDates);
+            case PAYLOADTYPE_PRIMITIVE:
+                return jsonLightReadTopPrimitiveProperty(data, typeName, baseURI, recognizeDates);
+            case PAYLOADTYPE_SVCDOC:
+                return jsonLightReadSvcDocument(data, baseURI);
+            case PAYLOADTYPE_LINKS:
+                return jsonLightReadLinksDocument(data, baseURI);
+        }
+    }
+    return jsonLightReadObject(data, payloadInfo, baseURI, model, recognizeDates);
+};
+
+var jsonLightGetEntryKey = function (data, entityModel) {
+    /// <summary>Gets the key of an entry.</summary>
+    /// <param name="data" type="Object">JSON light entry.</param>
+    /// <param name="entityModel" type="String">Object describing the entry Model</param>
+    /// <returns type="string">Entry instance key.</returns>
+
+    var entityInstanceKey;
+    var entityKeys = entityModel.key[0].propertyRef;
+    var type;
+    entityInstanceKey = "(";
+    if (entityKeys.length == 1) {
+        type = lookupProperty(entityModel.property, entityKeys[0].name).type;
+        entityInstanceKey += formatLiteral(data[entityKeys[0].name], type);
+    } else {
+        var first = true;
+        for (var i = 0; i < entityKeys.length; i++) {
+            if (!first) {
+                entityInstanceKey += ",";
+            } else {
+                first = false;
+            }
+            type = lookupProperty(entityModel.property, entityKeys[i].name).type;
+            entityInstanceKey += entityKeys[i].name + "=" + formatLiteral(data[entityKeys[i].name], type);
+        }
+    }
+    entityInstanceKey += ")";
+    return entityInstanceKey;
+};
+
+var jsonLightReadObjectNew = function (data, objectInfo, baseURI, model, demandedFormat, recognizeDates) {
+    //var obj = {};
+
+    data['@odata.type'] = '#'+objectInfo.typeName;
+
+    var keyType = objectInfo.type;
+    while (( keyType.key === undefined) && (keyType.baseType !== undefined)) {
+        keyType = lookupEntityType(keyType.baseType, model);
+    }
+
+    var lastIdSegment = objectInfo.name + jsonLightGetEntryKey(data, keyType);
+    data['@odata.id'] = baseURI.substring(0, baseURI.lastIndexOf("$metadata")) + lastIdSegment;
+    data['@odata.editLink'] = lastIdSegment;
+
+    var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
+    //jsonLightComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
+
+    
+
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var curType = objectInfo.type;
+            var propertyValue = data[name];
+            var property = lookupProperty(curType.property,name); //TODO SK add check for parent type
+
+            while (( property === null) && (curType.baseType !== undefined)) {
+                curType = lookupEntityType(curType.baseType, model);
+                property = lookupProperty(curType.property,name);
+            }
+            if (demandedFormat === 3)  {
+                if ( isArray(propertyValue)) {
+                    data[name+'@odata.type'] = '#' + property.type;
+                    for ( var i = 0; i < propertyValue.length; i++) {
+                        jsonLightReadComplexObjectNew(propertyValue[0], property,baseURI,model,demandedFormat, recognizeDates);
+                    }
+                } else if (isObject(propertyValue) && (propertyValue!= null)) {
+                    jsonLightReadComplexObjectNew(propertyValue, property,baseURI,model,demandedFormat, recognizeDates);
+                } else {
+                    data[name+'@odata.type'] = '#' + property.type;
+                }
+                
+            } else {
+
+            }
+        }
+    }
+
+    return data;
+};
+
+var jsonLightReadFeedNew = function (data, feedInfo, baseURI, model, demandedFormat,recognizeDates) {
+    var entries = [];
+    var items = data.value;
+    for (i = 0, len = items.length; i < len; i++) {
+        //TODO SK check if items[i] has @odata.type and use this type instead of  feedinfo
+        
+        if ( items[i]['@odata.type'] !== undefined) {
+            var typeName = items[i]['@odata.type'].substring(1);
+            var type = lookupEntityType( typeName, model);
+            var entryInfo = {
+                contentTypeOdata : feedInfo.contentTypeOdata,
+                detectedPayloadKind : feedInfo.detectedPayloadKind,
+                name : feedInfo.name,
+                type : type,
+                typeName : typeName
+            };
+
+            entry = jsonLightReadObjectNew(items[i], entryInfo, baseURI, model, demandedFormat,recognizeDates);
+        } else {
+            entry = jsonLightReadObjectNew(items[i], feedInfo, baseURI, model, demandedFormat,recognizeDates);
+        }
+        
+        entries.push(entry);
+    }
+    data.value = entries;
+    return data;
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+/*
 var jsonNormalizeData = function (data, baseURI) {
     /// <summary>
     /// Normalizes the specified data into an intermediate representation.
@@ -489,8 +911,154 @@
 
     var isSvcDoc = isComplex(data) && !data.__metadata && isArray(data.EntitySets);
     return isSvcDoc ? normalizeServiceDocument(data, baseURI) : data;
+};*/
+
+var formatLiteral = function (value, type) {
+    /// <summary>Formats a value according to Uri literal format</summary>
+    /// <param name="value">Value to be formatted.</param>
+    /// <param name="type">Edm type of the value</param>
+    /// <returns type="string">Value after formatting</returns>
+
+    value = "" + formatRowLiteral(value, type);
+    value = encodeURIComponent(value.replace("'", "''"));
+    switch ((type)) {
+        case "Edm.Binary":
+            return "X'" + value + "'";
+        case "Edm.DateTime":
+            return "datetime" + "'" + value + "'";
+        case "Edm.DateTimeOffset":
+            return "datetimeoffset" + "'" + value + "'";
+        case "Edm.Decimal":
+            return value + "M";
+        case "Edm.Guid":
+            return "guid" + "'" + value + "'";
+        case "Edm.Int64":
+            return value + "L";
+        case "Edm.Float":
+            return value + "f";
+        case "Edm.Double":
+            return value + "D";
+        case "Edm.Geography":
+            return "geography" + "'" + value + "'";
+        case "Edm.Geometry":
+            return "geometry" + "'" + value + "'";
+        case "Edm.Time":
+            return "time" + "'" + value + "'";
+        case "Edm.String":
+            return "'" + value + "'";
+        default:
+            return value;
+    }
 };
 
+var formatRowLiteral = function (value, type) {
+    switch (type) {
+        case "Edm.Binary":
+            return convertByteArrayToHexString(value);
+        default:
+            return value;
+    }
+};
+
+
+var jsonLightReadComplexObjectNew = function (data, property, baseURI, model, demandedFormat, recognizeDates) {
+    var type = property.type;
+    if (isCollectionType(property.type)) {
+        type =property.type.substring(11,property.type.length-1);
+    }
+
+    data['@odata.type'] = '#'+type;
+
+
+
+    var propertyType = lookupComplexType(type, model);
+    if (propertyType === null)  {
+        return; //TODO check what to do if the type is not known e.g. type #GeometryCollection
+    }
+
+    var curType = propertyType;
+
+
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var propertyValue = data[name];
+            var property = lookupProperty(curType.property,name); //TODO SK add check for parent type
+
+            while (( property === null) && (curType.baseType !== undefined)) {
+                curType = lookupEntityType(curType.baseType, model);
+                property = lookupProperty(curType.property,name);
+            }
+            if (demandedFormat === 3)  {
+                if ( isArray(propertyValue)) {
+                    data[name+'@odata.type'] = '#' + property.type;
+                    for ( var i = 0; i < propertyValue.length; i++) {
+                        jsonLightReadComplexObjectNew(propertyValue[0], property,baseURI,model,demandedFormat, recognizeDates);
+                    }
+                } else if (isObject(propertyValue) && (propertyValue!= null)) {
+                    jsonLightReadComplexObjectNew(propertyValue, property,baseURI,model,demandedFormat, recognizeDates);
+                } else {
+                    data[name+'@odata.type'] = '#' + property.type;
+                }
+                
+            } else {
+
+            }
+        }
+    }
+}
+
+
+var jsonLightReadObjectNew = function (data, objectInfo, baseURI, model, demandedFormat, recognizeDates) {
+    //var obj = {};
+
+    data['@odata.type'] = '#'+objectInfo.typeName;
+
+    var keyType = objectInfo.type;
+    while (( keyType.key === undefined) && (keyType.baseType !== undefined)) {
+        keyType = lookupEntityType(keyType.baseType, model);
+    }
+
+    var lastIdSegment = objectInfo.name + jsonLightGetEntryKey(data, keyType);
+    data['@odata.id'] = baseURI.substring(0, baseURI.lastIndexOf("$metadata")) + lastIdSegment;
+    data['@odata.editLink'] = lastIdSegment;
+
+    var serviceURI = baseURI.substring(0, baseURI.lastIndexOf("$metadata"));
+    //jsonLightComputeUrisIfMissing(data, entryInfo, actualType, serviceURI, dataModel, baseTypeModel);
+
+    
+
+    for (var name in data) {
+        if (name.indexOf("@") === -1) {
+            var curType = objectInfo.type;
+            var propertyValue = data[name];
+            var property = lookupProperty(curType.property,name); //TODO SK add check for parent type
+
+            while (( property === null) && (curType.baseType !== undefined)) {
+                curType = lookupEntityType(curType.baseType, model);
+                property = lookupProperty(curType.property,name);
+            }
+            if (demandedFormat === 3)  {
+                if ( isArray(propertyValue)) {
+                    data[name+'@odata.type'] = '#' + property.type;
+                    for ( var i = 0; i < propertyValue.length; i++) {
+                        jsonLightReadComplexObjectNew(propertyValue[0], property,baseURI,model,demandedFormat, recognizeDates);
+                    }
+                } else if (isObject(propertyValue) && (propertyValue!= null)) {
+                    jsonLightReadComplexObjectNew(propertyValue, property,baseURI,model,demandedFormat, recognizeDates);
+                } else {
+                    data[name+'@odata.type'] = '#' + property.type;
+                }
+                
+            } else {
+
+            }
+        }
+    }
+
+    return data;
+};
+
+
 var jsonHandler = oDataHandler.handler(jsonParser, jsonSerializer, jsonMediaType, MAX_DATA_SERVICE_VERSION);
 jsonHandler.recognizeDates = false;
 jsonHandler.useJsonLight = true;
@@ -503,9 +1071,10 @@
 // DATAJS INTERNAL START
 exports.jsonParser = jsonParser;
 exports.jsonSerializer = jsonSerializer;
-exports.jsonNormalizeData = jsonNormalizeData;
-exports.normalizeServiceDocument = normalizeServiceDocument;
+//exports.jsonNormalizeData = jsonNormalizeData;
+//exports.normalizeServiceDocument = normalizeServiceDocument;
 exports.parseJsonDateString = parseJsonDateString;
+exports.jsonLightPayloadInfo = jsonLightPayloadInfo;
 // DATAJS INTERNAL END