You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ko...@apache.org on 2014/06/23 17:29:31 UTC

git commit: [OLINGO-324] modify context type detection and first tests for this

Repository: olingo-odata4-js
Updated Branches:
  refs/heads/OLINGO-324 064542b83 -> ab2587ef3


[OLINGO-324] modify context type detection and first tests for this


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

Branch: refs/heads/OLINGO-324
Commit: ab2587ef360bec5d2f7076d46d40bc1cfef5276b
Parents: 064542b
Author: Sven Kobler <sv...@sap.com>
Authored: Mon Jun 23 17:29:13 2014 +0200
Committer: Sven Kobler <sv...@sap.com>
Committed: Mon Jun 23 17:29:13 2014 +0200

----------------------------------------------------------------------
 datajs/demo/scripts/.gitignore           |   2 +-
 datajs/demo/tester.html                  |  65 ++++++++++++-
 datajs/src/lib/datajs/utils.js           |   8 ++
 datajs/src/lib/odata/json-light.js       | 132 +++++++++++++++++++++++---
 datajs/src/lib/odata/json.js             |  23 +++--
 datajs/src/lib/odata/utils.js            |  13 +++
 datajs/tests/odata-json-parse-tests.html |  46 +++++++++
 datajs/tests/odata-json-parse-tests.js   |  99 +++++++++++++++++++
 8 files changed, 360 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/demo/scripts/.gitignore
----------------------------------------------------------------------
diff --git a/datajs/demo/scripts/.gitignore b/datajs/demo/scripts/.gitignore
index 7318683..863d40c 100644
--- a/datajs/demo/scripts/.gitignore
+++ b/datajs/demo/scripts/.gitignore
@@ -1 +1 @@
-demo/scripts/datajs-2*
+datajs-2*

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/demo/tester.html
----------------------------------------------------------------------
diff --git a/datajs/demo/tester.html b/datajs/demo/tester.html
index 11cc85f..43bca29 100644
--- a/datajs/demo/tester.html
+++ b/datajs/demo/tester.html
@@ -31,11 +31,13 @@
         <button id="startXML">XML</button><br/>
         <button id="btnJSON_none">pure JSON odata.metadata=none</button><br/>
         <button id="btnJSON_minimal">pure JSON odata.metadata=minimal</button><br/>
+        <button id="btnJSON_minimal_to_full">pure JSON odata.metadata=minimal; extendMetadataToLevel=full</button><br/>
+        <button id="btnJSON_minimal_to_all">pure JSON odata.metadata=minimal; extendMetadataToLevel=all</button><br/>
         <button id="btnJSON_full">pure JSON odata.metadata=full</button><br/>
-        <button id="btnJSON_full_date_conversion">JSON odata.metadata=full with date conversion</button><br/>
-        <button id="btnJSON_all">JSON odata.metadata=full with adding types for string, bool, numbers</button><br/>
+        <button id="btnJSON_full_date_conversion">JSON odata.metadata=full (with date conversion)</button><br/>
+        <button id="btnJSON_full_to_all">JSON odata.metadata=full; extendMetadataToLevel=all (with adding types for string, bool, numbers)</button><br/>
+        <button id="btnJSON_full_to_all_date_conversion">JSON odata.metadata=full; extendMetadataToLevel=all (with adding types for string, bool, numbers) (with date conversion)</button><br/>
 
-        
         <button id="btnMetaData">MetaData</button><br/>
         <button id="btnJSONwithMetaData">JSON with MetaData</button><br/>
         <div id='resultsArea' data-type="json">
@@ -62,6 +64,23 @@
                 $("#resultsArea").text(JSON.stringify(err));
             }
 
+            function getMetaData(metaDatasuccess) {
+                var oHeaders = {
+                    'Accept': 'text/html,application/xhtml+xml,application/xml,application/json;odata.metadata=full',
+                    "Odata-Version": "4.0",
+                    "OData-MaxVersion": "4.0",
+                    "Prefer": "odata.allow-entityreferences"
+                };
+                var metadataRequest =
+                {
+                    headers: oHeaders,
+                    //requestUri: "http://services.odata.org/OData/OData.svc/$metadata",
+                    requestUri: "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata", //"http://localhost:6630/PrimitiveKeys.svc/$metadata",
+                    data: null,
+                };
+                OData.read(metadataRequest, metaDatasuccess, errorFunc,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';
@@ -89,7 +108,16 @@
                 OData.read(requestUri, success, errorFunc);
             });
 
-            $('#btnJSON_all').on("click", function(){
+            $('#btnJSON_full_to_all').on("click", function(){
+                var requestUri = {
+                    requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
+                    headers : { Accept : 'application/json;odata.metadata=full' },
+                    extendMetadataToLevel : 'all' ,
+                    recognizeDates : false
+                };
+                OData.read(requestUri, success, errorFunc);
+            });
+            $('#btnJSON_full_to_all_date_conversion').on("click", function(){
                 var requestUri = {
                     requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
                     headers : { Accept : 'application/json;odata.metadata=full' },
@@ -124,6 +152,35 @@
 
                 OData.read(metadataRequest, success, errorFunc,OData.metadataHandler);
             });
+
+
+
+            $('#btnJSON_minimal_to_all').on("click", function(){
+                var metaDatasuccess = function(metadata){
+                    var requestUri = {
+                        requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
+                        headers : { Accept : 'application/json;odata.metadata=minimal' },
+                        extendMetadataToLevel : 'all' ,
+                        recognizeDates : false
+                    };
+                    OData.read(requestUri, success, errorFunc, null, null, metadata);
+                }
+                getMetaData(metaDatasuccess);
+            });
+
+            $('#btnJSON_minimal_to_full').on("click", function(){
+                var metaDatasuccess = function(metadata){
+                    var requestUri = {
+                        requestUri : 'http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/Foods',
+                        headers : { Accept : 'application/json;odata.metadata=minimal' },
+                        extendMetadataToLevel : 'full' ,
+                        recognizeDates : false
+                    };
+                    OData.read(requestUri, success, errorFunc, null, null, metadata);
+                }
+                getMetaData(metaDatasuccess);
+            });
+
             $('#btnJSONwithMetaData').on("click", function(){
                 var oHeaders = {
                     'Accept': 'text/html,application/xhtml+xml,application/xml,application/json;odata.metadata=full',

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/src/lib/datajs/utils.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/datajs/utils.js b/datajs/src/lib/datajs/utils.js
index bd4f287..639a199 100644
--- a/datajs/src/lib/datajs/utils.js
+++ b/datajs/src/lib/datajs/utils.js
@@ -523,6 +523,12 @@ var endsWith = function (input, search) {
     return input.indexOf(search, input.length - search.length) !== -1;
 };
 
+var startsWith = function (input, search) {
+    return input.indexOf(search) == 0;
+};
+
+
+
 // DATAJS INTERNAL START
 exports.activeXObject = activeXObject;
 exports.assigned = assigned;
@@ -548,7 +554,9 @@ exports.convertByteArrayToHexString = convertByteArrayToHexString;
 exports.getJsonValueArraryLength = getJsonValueArraryLength;
 exports.sliceJsonValueArray = sliceJsonValueArray;
 exports.concatJsonValueArray = concatJsonValueArray;
+exports.startsWith = startsWith;
 exports.endsWith = endsWith;
+
 // DATAJS INTERNAL END
 
     
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/src/lib/odata/json-light.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/json-light.js b/datajs/src/lib/odata/json-light.js
index 17c2cba..12c5d84 100644
--- a/datajs/src/lib/odata/json-light.js
+++ b/datajs/src/lib/odata/json-light.js
@@ -1052,14 +1052,19 @@ var jsonLightMakePayloadInfo = function (kind, type) {
     return { kind: kind, type: type || null };
 };
 
-/**/
-var parseContextUriFragment = function( fragment ) {
+/// <summary>Creates an object containing information for the context</summary>
+/// ...
+/// <returns type="Object">Object with type information
+/// attribute detectedPayloadKind: see constants starting with PAYLOADTYPE_
+/// attribute deltaKind: deltainformation, one of the following valus DELTATYPE_FEED | DELTATYPE_DELETED_ENTRY | DELTATYPE_LINK | DELTATYPE_DELETED_LINK
+/// attribute typeName: name of the type
+/// attribute type: object containing type information for entity- and complex-types
+///  </returns>
+var parseContextUriFragment = function( fragment, model ) {
     var ret = {};
 
     ret.deltaKind = undefined;
-    if (utils.endsWith(fragment, '/$entity')) {
-        fragment = fragment.substring(fragment.lenght - 8);
-    } else if (utils.endsWith(fragment, '/$delta')) {
+    if (utils.endsWith(fragment, '/$delta')) {
         ret.deltaKind = DELTATYPE_FEED;
         fragment = fragment.substring(fragment.lenght - 7);
     } else if (utils.endsWith(fragment, '/$deletedEntity')) {
@@ -1084,7 +1089,7 @@ var parseContextUriFragment = function( fragment ) {
             }
         }
 
-        if (index == 0) {
+        if (index === 0) {
             //TODO throw error
         }
 
@@ -1092,7 +1097,7 @@ var parseContextUriFragment = function( fragment ) {
 
 
         if (previous !== 'Collection') { // Don't treat Collection(Edm.Type) as SelectExpand segment
-            var selectExpandStr = fragment.substring(index+2, fragment.lenght - 1);
+            var selectExpandStr = fragment.substring(index+2, fragment.length - 1);
             var keyPattern = /^(?:-{0,1}\d+?|\w*'.+?'|[A-F0-9]{8}(?:-[A-F0-9]{4}){3}-[A-F0-9]{12}|.+?=.+?)$/;
             var matches = keyPattern.exec(selectExpandStr);
             if ( matches ) {
@@ -1110,29 +1115,129 @@ var parseContextUriFragment = function( fragment ) {
         if (fragment.length === 0) {
             // Capter 10.1
             ret.detectedPayloadKind = PAYLOADTYPE_SVCDOC;
+            return ret;
         } else if (fragment === 'Edm.Null') {
             // Capter 10.15
             ret.detectedPayloadKind = PAYLOADTYPE_PROPERTY;
             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.lastType = undefined;
+    ret.lastTypeName = undefined;
+    ret.detectedPayloadKind = undefined;
+
     // split fragment at '/'
     //TODO changes
     var fragmentParts = fragment.split("/");
-    if (fragmentParts.length >= 0) {
+    
+
+    for(var i = 0; i < fragmentParts.length; ++i) {
+        var fragment = fragmentParts[i];
+        if (ret.lastTypeName === undefined) {
+            //preparation
+            var startPharen = fragment.indexOf('(')
+            var inPharenthesis = undefined;
+            if ( startPharen !== -1 ) {
+                //remove the projected entity from the fragment; TODO decide if we want to store the projected entity 
+                inPharenthesis = fragment.substring(startPharen+1,fragment.length - 1);
+                // projection: Capter 10.7, 10.8 and 10.9
+                fragment = fragment.substring(0,startPharen);
+
+                if (utils.startsWith(fragment, 'Collection')) {
+                    ret.detectedPayloadKind = PAYLOADTYPE_COLLECTION;
+                    // Capter 10.14
+                    ret.lastTypeName = inPharenthesis;
+
+                    ret.lastType = lookupEntityType( ret.lastTypeName, model);
+                } else {
+                    ret.projection = inPharenthesis;
+                }
+            }
+
+            var container = lookupDefaultEntityContainer(model);
+
+            //check for entity
+            var entitySet = lookupEntitySet(container.entitySet, fragment);
+            if ( entitySet !== undefined) {
+                ret.lastTypeName = entitySet.entityType;
+                ret.lastType = lookupEntityType( ret.lastTypeName, model);
+                ret.detectedPayloadKind = PAYLOADTYPE_FEED;
+                // Capter 10.2
+                continue;
+            }
+
+            //check for singleton
+            var singleton = lookupSingleton(container.singleton, fragment);
+            if ( singleton !== undefined) {
+                ret.lastTypeName = singleton.entityType;
+                ret.lastType = lookupEntityType( ret.lastTypeName, model);
+                ret.detectedPayloadKind =  PAYLOADTYPE_ENTRY;
+                // Capter 10.4
+                continue;
+            }
+
+        } 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.lastTypeName = fragment;
+                var type = lookupEntityType(ret.lastTypeName, model);
+                if ( entitySet !== undefined) {
+                    ret.lastType = type;
+                    continue;
+                }
+                type = lookupComplexType(ret.lastTypeName, model);
+                if ( entitySet !== undefined) {
+                    ret.lastType = type;
+                    continue;
+                }
+
+                //ERROR invalid type
+            }
+
+            //check for property value
+            if ( ret.detectedPayloadKind === PAYLOADTYPE_FEED || ret.detectedPayloadKind === PAYLOADTYPE_ENTRY) {
+                var property = lookupProperty(ret.lastType.properties, fragment);
+                if (property !== undefined) {
+                    ret.lastTypeName = property.type;
+                    if (!jsonLightIsPrimitiveType(ret.lastTypeName)) {
+                        ret.lastType = lookupComplexType(ret.lastTypeName, model);
+                    } else {
+                        ret.lastType = undefined;
+                    }
+                    ret.detectedPayloadKind === PAYLOADTYPE_PROPERTY;
+                    // Capter 10.15
+                }
+                continue;
+            }
+        }
+    }
+    return ret;
+
+/*
         var qualifiedName = fragmentParts[0];
         var typeCast = fragmentParts[1];
 
-        if (jsonLightIsPrimitiveType(qualifiedName)) {
+        if () {
             ret.detectedPayloadKind  = PAYLOADTYPE_VALUE;
             return ret;
         }
@@ -1186,7 +1291,7 @@ var parseContextUriFragment = function( fragment ) {
 
         return jsonLightMakePayloadInfo(PAYLOADTYPE_OBJECT, qualifiedName);
     }
-
+*/
 };
 
 var jsonLightPayloadInfo = function (data, model) {
@@ -1213,7 +1318,7 @@ var jsonLightPayloadInfo = function (data, model) {
         return jsonLightMakePayloadInfo(PAYLOADTYPE_SVCDOC);
     }
 
-    var d = metadataUri.indexOf("@Element", fragmentStart);
+    var elementStart = metadataUri.indexOf("@Element", fragmentStart);
     var fragmentEnd = elementStart - 1;
 
     if (fragmentEnd < 0) {
@@ -1228,9 +1333,9 @@ var jsonLightPayloadInfo = function (data, model) {
         return jsonLightMakePayloadInfo(PAYLOADTYPE_LINKS);
     }
 
-    var ret = parseContextUriFragment(fragment);
+    var ret = parseContextUriFragment(fragment,model);
 
-    return;
+    return ret;
 
 
 };
@@ -1546,6 +1651,7 @@ var formatJsonLightAnnotation = function (qName, target, value, data) {
 };
 
 // DATAJS INTERNAL START
+exports.jsonLightPayloadInfo = jsonLightPayloadInfo;
 exports.jsonLightReadPayload = jsonLightReadPayload;
 exports.formatJsonLight = formatJsonLight;
 exports.formatJsonLightRequestPayload = formatJsonLightRequestPayload;

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/src/lib/odata/json.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/json.js b/datajs/src/lib/odata/json.js
index 90758e0..f5293bf 100644
--- a/datajs/src/lib/odata/json.js
+++ b/datajs/src/lib/odata/json.js
@@ -46,6 +46,7 @@ var handler = oDataUtils.handler;
 var isComplex = oDataUtils.isComplex;
 var lookupComplexType = oDataUtils.lookupComplexType;
 var lookupEntityType = oDataUtils.lookupEntityType;
+var lookupSingleton = oDataUtils.lookupSingleton;
 var MAX_DATA_SERVICE_VERSION = oDataUtils.MAX_DATA_SERVICE_VERSION;
 var maxVersion = oDataUtils.maxVersion;
 var parseDateTime = oDataUtils.parseDateTime;
@@ -253,7 +254,7 @@ var jsonParser = function (handler, text, context) {
 
     var payloadFormat = 1;//minmal
     try {
-        payloadFormat = metadataMap[context.contentType.properties["odata.metadata"]]; 
+        payloadFormat = metadataMap[context.contentType.properties["odata.metadata"]];//TODO convert to lower before comparism
     } catch(err) {
         payloadFormat = 1;
     }
@@ -261,7 +262,7 @@ var jsonParser = function (handler, text, context) {
 
     var demandedFormat = 1;//minmal
     try {
-        demandedFormat = metadataMap[context.extendMetadataToLevel]; 
+        demandedFormat = metadataMap[context.extendMetadataToLevel]; //TODO convert to lower before comparism
     } catch(err) {
         demandedFormat = 1;
     }
@@ -290,12 +291,12 @@ var jsonParser = function (handler, text, context) {
             //guess types for nummber as defined in the odata-json-format-v4.0.doc specification
             return extendMetadataFromPayload(json,context,recognizeDates);
         } else if (payloadFormat === 1) { //minmal
-            if (utils.isArray(context.metadata)) {
+            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,recognizeDates);
+                return extendMetadataFromContext(json,context,model,recognizeDates);
             } else {
-                //error metadata in context required
+                //error metadata in context required, TODO: throw a to be defined exception
             }
         } else {
             // the payload contains no context url only guessing possible
@@ -306,8 +307,8 @@ var jsonParser = function (handler, text, context) {
     
 };
 
-var extendMetadataFromContext = function(json,context,recognizeDates) {
-    return jsonLightReadPayload(json, model, recognizeDates, inferJsonLightFeedAsObject, context.contentType.properties['odata.metadata']);
+var extendMetadataFromContext = function(json,context, model,recognizeDates) {
+    return jsonLightReadPayload(json, model, recognizeDates, false, context.contentType.properties['odata.metadata']);
 };
 
 var convertPrimitivetypesGeneric = function(data) {
@@ -342,6 +343,7 @@ var convertPrimitivetypesOnMetadataFull = function(data) {
                         } else if ( type === '#DateTime' ) {
                            data[key] = oDataUtils.parseDateTimeOffset(data[key],true);
                         }
+                        //TODO handle more types there 
                     }
                 }
             }
@@ -393,6 +395,7 @@ var extendMetadataFromPayload = function(data,context,recognizeDates) {
                             } else if ( type === '#DateTime' ) {
                                data[key] = oDataUtils.parseDateTimeOffset(data[key],true);
                             }
+                            //TODO handle more types there 
                         }
                         var typeFromObject = typeof data[key];
                         if ( typeFromObject === 'string' ) {
@@ -400,10 +403,10 @@ var extendMetadataFromPayload = function(data,context,recognizeDates) {
                         } else if (typeFromObject ==='boolean') {
                             addType(data,key,'#Bool');
                         } else if (typeFromObject ==='number') {
-                            if ( data[key] % 1 === 0 ) {
-                                addType(data,key,'#Integer');
+                            if ( data[key] % 1 === 0 ) { // has fraction 
+                                addType(data,key,'#Integer');// the biggst integer
                             } else {
-                                addType(data,key,'#Decimal');
+                                addType(data,key,'#Decimal');// the biggst float single,doulbe,decimal
                             }
                         }
                     }

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/src/lib/odata/utils.js
----------------------------------------------------------------------
diff --git a/datajs/src/lib/odata/utils.js b/datajs/src/lib/odata/utils.js
index 552fb77..e99b2c1 100644
--- a/datajs/src/lib/odata/utils.js
+++ b/datajs/src/lib/odata/utils.js
@@ -539,6 +539,17 @@ var lookupEntitySet = function (entitySets, name) {
     });
 };
 
+var lookupSingleton = function (singletons, name) {
+    /// <summary>Looks up a entity set by name.</summary>
+    /// <param name="properties" type="Array" mayBeNull="true">Array of entity set objects as per EDM metadata.</param>
+    /// <param name="name" type="String">Name to look for.</param>
+    /// <returns type="Object">The entity set object; null if not found.</returns>
+
+    return find(singletons, function (singleton) {
+        return singleton.name === name;
+    });
+};
+
 var lookupComplexType = function (name, metadata) {
     /// <summary>Looks up a complex type object by name.</summary>
     /// <param name="name" type="String">Name, possibly null or empty.</param>
@@ -557,6 +568,7 @@ var lookupEntityType = function (name, metadata) {
     return lookupInMetadata(name, metadata, "entityType");
 };
 
+
 var lookupDefaultEntityContainer = function (metadata) {
     /// <summary>Looks up an</summary>
     /// <param name="name" type="String">Name, possibly null or empty.</param>
@@ -1126,6 +1138,7 @@ exports.lookupComplexType = lookupComplexType;
 exports.lookupDefaultEntityContainer = lookupDefaultEntityContainer;
 exports.lookupEntityContainer = lookupEntityContainer;
 exports.lookupEntitySet = lookupEntitySet;
+exports.lookupSingleton = lookupSingleton;
 exports.lookupEntityType = lookupEntityType;
 exports.lookupFunctionImport = lookupFunctionImport;
 exports.lookupNavigationPropertyType = lookupNavigationPropertyType;

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/tests/odata-json-parse-tests.html
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-json-parse-tests.html b/datajs/tests/odata-json-parse-tests.html
new file mode 100644
index 0000000..8aa847b
--- /dev/null
+++ b/datajs/tests/odata-json-parse-tests.html
@@ -0,0 +1,46 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
+<html>
+<!--
+Copyright (c) Microsoft Open Technologies, Inc.  All rights reserved.
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation 
+files (the "Software"), to deal  in the Software without restriction, including without limitation the rights  to use, copy,
+modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the 
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+-->
+  <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
+    <meta http-equiv="cache-control" content="no-cache" />
+    <meta http-equiv="pragma" content="no-cache" />
+    <meta http-equiv="expires" content="-1" />
+
+    <title>OData unit tests</title>
+    <link rel="stylesheet" href="http://code.jquery.com/qunit/qunit-1.10.0.css" type="text/css" />
+    
+    <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.4.min.js" ></script>
+    
+    <script type="text/javascript" src="http://code.jquery.com/qunit/qunit-1.10.0.js"></script>
+    <script type="text/javascript" src="http://cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js"></script>
+    <script type="text/javascript" src="common/TestSynchronizerClient.js"></script>
+    <script type="text/javascript">
+        window.TestSynchronizer.init(QUnit);
+    </script>
+   
+    <script type="text/javascript" src="../build/datajs-2.0.0.js"></script>   
+    <script type="text/javascript" src="common/djstest.js"></script>
+    <script type="text/javascript" src="odata-json-parse-tests.js"></script>
+  </head>
+  <body>
+    <h1 id="qunit-header">OData Unit Tests</h1>
+    <h2 id="qunit-banner"></h2>
+    <h2 id="qunit-userAgent"></h2>
+    <ol id="qunit-tests">
+    </ol>
+  </body>
+</html>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/olingo-odata4-js/blob/ab2587ef/datajs/tests/odata-json-parse-tests.js
----------------------------------------------------------------------
diff --git a/datajs/tests/odata-json-parse-tests.js b/datajs/tests/odata-json-parse-tests.js
new file mode 100644
index 0000000..c2dd33a
--- /dev/null
+++ b/datajs/tests/odata-json-parse-tests.js
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+// odata-tests.js
+(function (window, undefined) {
+    function errorFunc() {
+        djstest.fail('Errror');
+    }
+
+    function runWithMetadata(metaDatasuccess) {
+
+        
+        var oHeaders = {
+            'Accept': 'text/html,application/xhtml+xml,application/xml,application/json;odata.metadata=full',
+            "Odata-Version": "4.0",
+            "OData-MaxVersion": "4.0",
+            "Prefer": "odata.allow-entityreferences"
+        };
+        var metadataRequest =
+        {
+            headers: oHeaders,
+            //requestUri: "http://services.odata.org/OData/OData.svc/$metadata",
+            requestUri: "http://localhost:4002/tests/endpoints/FoodStoreDataServiceV4.svc/$metadata", //"http://localhost:6630/PrimitiveKeys.svc/$metadata",
+            data: null,
+        };
+        OData.read(metadataRequest, metaDatasuccess, errorFunc,OData.metadataHandler);
+    };
+
+    djstest.addTest(function test1() {
+        var checkLastTypeName = function (metadata, input, expected) {
+            var info = OData.jsonLight.jsonLightPayloadInfo({ "@odata.context" : input}, metadata)
+            djstest.assertAreEqual(info.lastTypeName,expected, "Test context fragment: "+ input);
+
+        };
+
+        var checkKind = function (metadata, input, expected) {
+            var info = OData.jsonLight.jsonLightPayloadInfo({ "@odata.context" : input}, metadata)
+            djstest.assertAreEqual(info.detectedPayloadKind,expected, "Test context fragment: "+ input);
+        };
+        var success = function(metadata){
+            //Chapter 10.1
+            checkKind(metadata, '#', 's');
+            //Chapter 10.2
+            checkKind(metadata, '#Foods', 'f');
+            //Chapter 10.3
+            checkKind(metadata, '#Foods/$entity', 'e');
+            //Chapter 10.4
+            //checkKind(metadata, '#Singleton', '');
+            //Chapter 10.5
+            checkKind(metadata, '#Foods/DataJS.Tests.V4.Food', 'f');
+            //Chapter 10.6
+            checkKind(metadata, '#Foods/DataJS.Tests.V4.Food/$entity', 'e');
+            //Chapter 10.7
+            checkKind(metadata, '#Foods(FoodID,Name)', 'f');
+            //Chapter 10.8
+            checkKind(metadata, '#Foods(FoodID,Name)/$entity', 'e');
+            //Chapter 10.9
+            checkKind(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))', 'f');
+            //Chapter 10.10
+            checkKind(metadata, '#Foods(FoodID,Name,Category,Category+(CategoryID,Name))/$entity', 'e');
+            //Chapter 10.11
+            checkKind(metadata, '#Collection($ref)', 'erls');
+            //Chapter 10.12
+            checkKind(metadata, '#$ref', 'erl');
+            //Chapter 10.13
+            checkKind(metadata, '#Foods(0)/Packaging', 'p');
+            //Chapter 10.14
+            checkKind(metadata, '#Collection(Edm.String)', 'c');
+            //Chapter 10.15
+            checkKind(metadata, '#Edm.String', 'v');
+            //TODO add tests for delta tokens
+
+
+
+            checkLastTypeName(metadata, '#Foods', 'DataJS.Tests.V4.Food');
+            djstest.done();
+        };
+
+        runWithMetadata(success);
+    },'simple');
+
+
+})(this);